1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
4  */
5 
6 #include <linux/slab.h>
7 #include <linux/mm.h>
8 
9 #include "user_config.h"
10 #include "../transport_ipc.h"
11 
ksmbd_login_user(const char * account)12 struct ksmbd_user *ksmbd_login_user(const char *account)
13 {
14 	struct ksmbd_login_response *resp;
15 	struct ksmbd_login_response_ext *resp_ext = NULL;
16 	struct ksmbd_user *user = NULL;
17 
18 	resp = ksmbd_ipc_login_request(account);
19 	if (!resp)
20 		return NULL;
21 
22 	if (!(resp->status & KSMBD_USER_FLAG_OK))
23 		goto out;
24 
25 	if (resp->status & KSMBD_USER_FLAG_EXTENSION)
26 		resp_ext = ksmbd_ipc_login_request_ext(account);
27 
28 	user = ksmbd_alloc_user(resp, resp_ext);
29 out:
30 	kvfree(resp);
31 	return user;
32 }
33 
ksmbd_alloc_user(struct ksmbd_login_response * resp,struct ksmbd_login_response_ext * resp_ext)34 struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
35 		struct ksmbd_login_response_ext *resp_ext)
36 {
37 	struct ksmbd_user *user;
38 
39 	user = kmalloc(sizeof(struct ksmbd_user), GFP_KERNEL);
40 	if (!user)
41 		return NULL;
42 
43 	user->name = kstrdup(resp->account, GFP_KERNEL);
44 	user->flags = resp->status;
45 	user->gid = resp->gid;
46 	user->uid = resp->uid;
47 	user->passkey_sz = resp->hash_sz;
48 	user->passkey = kmalloc(resp->hash_sz, GFP_KERNEL);
49 	if (user->passkey)
50 		memcpy(user->passkey, resp->hash, resp->hash_sz);
51 
52 	user->ngroups = 0;
53 	user->sgid = NULL;
54 
55 	if (!user->name || !user->passkey)
56 		goto err_free;
57 
58 	if (resp_ext) {
59 		if (resp_ext->ngroups > NGROUPS_MAX) {
60 			pr_err("ngroups(%u) from login response exceeds max groups(%d)\n",
61 					resp_ext->ngroups, NGROUPS_MAX);
62 			goto err_free;
63 		}
64 
65 		user->sgid = kmemdup(resp_ext->____payload,
66 				     resp_ext->ngroups * sizeof(gid_t),
67 				     GFP_KERNEL);
68 		if (!user->sgid)
69 			goto err_free;
70 
71 		user->ngroups = resp_ext->ngroups;
72 		ksmbd_debug(SMB, "supplementary groups : %d\n", user->ngroups);
73 	}
74 
75 	return user;
76 
77 err_free:
78 	kfree(user->name);
79 	kfree(user->passkey);
80 	kfree(user);
81 	return NULL;
82 }
83 
ksmbd_free_user(struct ksmbd_user * user)84 void ksmbd_free_user(struct ksmbd_user *user)
85 {
86 	ksmbd_ipc_logout_request(user->name, user->flags);
87 	kfree(user->sgid);
88 	kfree(user->name);
89 	kfree(user->passkey);
90 	kfree(user);
91 }
92 
ksmbd_anonymous_user(struct ksmbd_user * user)93 int ksmbd_anonymous_user(struct ksmbd_user *user)
94 {
95 	if (user->name[0] == '\0')
96 		return 1;
97 	return 0;
98 }
99 
ksmbd_compare_user(struct ksmbd_user * u1,struct ksmbd_user * u2)100 bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2)
101 {
102 	if (strcmp(u1->name, u2->name))
103 		return false;
104 	if (memcmp(u1->passkey, u2->passkey, u1->passkey_sz))
105 		return false;
106 
107 	return true;
108 }
109