1/* 2 Unix SMB/CIFS implementation. 3 async fill_pwent 4 Copyright (C) Volker Lendecke 2009 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21#include "winbindd.h" 22#include "librpc/gen_ndr/cli_wbint.h" 23 24struct wb_fill_pwent_state { 25 struct tevent_context *ev; 26 struct wbint_userinfo *info; 27 struct winbindd_pw *pw; 28}; 29 30static bool fillup_pw_field(const char *lp_template, 31 const char *username, 32 const char *domname, 33 uid_t uid, 34 gid_t gid, 35 const char *in, 36 fstring out); 37 38static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq); 39static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq); 40 41struct tevent_req *wb_fill_pwent_send(TALLOC_CTX *mem_ctx, 42 struct tevent_context *ev, 43 struct wbint_userinfo *info, 44 struct winbindd_pw *pw) 45{ 46 struct tevent_req *req, *subreq; 47 struct wb_fill_pwent_state *state; 48 49 req = tevent_req_create(mem_ctx, &state, struct wb_fill_pwent_state); 50 if (req == NULL) { 51 return NULL; 52 } 53 state->ev = ev; 54 state->info = info; 55 state->pw = pw; 56 57 subreq = wb_sid2uid_send(state, state->ev, &state->info->user_sid); 58 if (tevent_req_nomem(subreq, req)) { 59 return tevent_req_post(req, ev); 60 } 61 tevent_req_set_callback(subreq, wb_fill_pwent_sid2uid_done, req); 62 return req; 63} 64 65static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq) 66{ 67 struct tevent_req *req = tevent_req_callback_data( 68 subreq, struct tevent_req); 69 struct wb_fill_pwent_state *state = tevent_req_data( 70 req, struct wb_fill_pwent_state); 71 NTSTATUS status; 72 73 status = wb_sid2uid_recv(subreq, &state->pw->pw_uid); 74 TALLOC_FREE(subreq); 75 if (!NT_STATUS_IS_OK(status)) { 76 tevent_req_nterror(req, status); 77 return; 78 } 79 80 subreq = wb_sid2gid_send(state, state->ev, &state->info->group_sid); 81 if (tevent_req_nomem(subreq, req)) { 82 return; 83 } 84 tevent_req_set_callback(subreq, wb_fill_pwent_sid2gid_done, req); 85} 86 87static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq) 88{ 89 struct tevent_req *req = tevent_req_callback_data( 90 subreq, struct tevent_req); 91 struct wb_fill_pwent_state *state = tevent_req_data( 92 req, struct wb_fill_pwent_state); 93 struct winbindd_domain *domain; 94 char *dom_name; 95 fstring user_name, output_username; 96 char *mapped_name = NULL; 97 NTSTATUS status; 98 99 status = wb_sid2gid_recv(subreq, &state->pw->pw_gid); 100 TALLOC_FREE(subreq); 101 if (!NT_STATUS_IS_OK(status)) { 102 tevent_req_nterror(req, status); 103 return; 104 } 105 106 domain = find_domain_from_sid_noinit(&state->info->user_sid); 107 if (domain == NULL) { 108 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 109 return; 110 } 111 dom_name = domain->name; 112 113 /* Username */ 114 115 fstrcpy(user_name, state->info->acct_name); 116 strlower_m(user_name); 117 status = normalize_name_map(state, domain, user_name, &mapped_name); 118 119 /* Basic removal of whitespace */ 120 if (NT_STATUS_IS_OK(status)) { 121 fill_domain_username(output_username, dom_name, mapped_name, 122 true); 123 } 124 /* Complete name replacement */ 125 else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) { 126 fstrcpy(output_username, mapped_name); 127 } 128 /* No change at all */ 129 else { 130 fill_domain_username(output_username, dom_name, user_name, 131 true); 132 } 133 134 fstrcpy(state->pw->pw_name, output_username); 135 fstrcpy(state->pw->pw_gecos, state->info->full_name); 136 137 /* Home directory and shell */ 138 139 if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, 140 state->pw->pw_uid, state->pw->pw_gid, 141 state->info->homedir, state->pw->pw_dir)) { 142 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 143 return; 144 } 145 146 if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, 147 state->pw->pw_uid, state->pw->pw_gid, 148 state->info->shell, state->pw->pw_shell)) { 149 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 150 return; 151 } 152 153 /* Password - set to "*" as we can't generate anything useful here. 154 Authentication can be done using the pam_winbind module. */ 155 156 fstrcpy(state->pw->pw_passwd, "*"); 157 tevent_req_done(req); 158} 159 160NTSTATUS wb_fill_pwent_recv(struct tevent_req *req) 161{ 162 return tevent_req_simple_recv_ntstatus(req); 163} 164 165static bool fillup_pw_field(const char *lp_template, 166 const char *username, 167 const char *domname, 168 uid_t uid, 169 gid_t gid, 170 const char *in, 171 fstring out) 172{ 173 char *templ; 174 175 if (out == NULL) 176 return False; 177 178 /* The substitution of %U and %D in the 'template 179 homedir' is done by talloc_sub_specified() below. 180 If we have an in string (which means the value has already 181 been set in the nss_info backend), then use that. 182 Otherwise use the template value passed in. */ 183 184 if ((in != NULL) && (in[0] != '\0') && (lp_security() == SEC_ADS)) { 185 templ = talloc_sub_specified(talloc_tos(), in, 186 username, domname, 187 uid, gid); 188 } else { 189 templ = talloc_sub_specified(talloc_tos(), lp_template, 190 username, domname, 191 uid, gid); 192 } 193 194 if (!templ) 195 return False; 196 197 safe_strcpy(out, templ, sizeof(fstring) - 1); 198 TALLOC_FREE(templ); 199 200 return True; 201 202} 203