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