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 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 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), KSMBD_DEFAULT_GFP); 40 if (!user) 41 return NULL; 42 43 user->name = kstrdup(resp->account, KSMBD_DEFAULT_GFP); 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, KSMBD_DEFAULT_GFP); 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 KSMBD_DEFAULT_GFP); 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 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 93 int ksmbd_anonymous_user(struct ksmbd_user *user) 94 { 95 if (user->name[0] == '\0') 96 return 1; 97 return 0; 98 } 99 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