2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* Required Headers */
24 #include "libwbclient.h"
26 /** @brief Authenticate a username/password pair
28 * @param username Name of user to authenticate
29 * @param password Clear text password os user
34 wbcErr wbcAuthenticateUser(const char *username,
37 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
38 struct winbindd_request request;
39 struct winbindd_response response;
42 wbc_status = WBC_ERR_INVALID_PARAM;
43 BAIL_ON_WBC_ERROR(wbc_status);
46 /* Initialize request */
49 ZERO_STRUCT(response);
51 /* dst is already null terminated from the memset above */
53 strncpy(request.data.auth.user, username,
54 sizeof(request.data.auth.user)-1);
55 strncpy(request.data.auth.pass, password,
56 sizeof(request.data.auth.user)-1);
58 wbc_status = wbcRequestResponse(WINBINDD_PAM_AUTH,
61 BAIL_ON_WBC_ERROR(wbc_status);
67 static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
68 const struct winbindd_response *resp,
69 struct wbcAuthUserInfo **_i)
71 wbcErr wbc_status = WBC_ERR_SUCCESS;
72 struct wbcAuthUserInfo *i;
73 struct wbcDomainSid domain_sid;
78 i = talloc(mem_ctx, struct wbcAuthUserInfo);
79 BAIL_ON_PTR_ERROR(i, wbc_status);
81 i->user_flags = resp->data.auth.info3.user_flgs;
83 i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name);
84 BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
85 i->user_principal= NULL;
86 i->full_name = talloc_strdup(i, resp->data.auth.info3.full_name);
87 BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
88 i->domain_name = talloc_strdup(i, resp->data.auth.info3.logon_dom);
89 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
90 i->dns_domain_name= NULL;
92 i->acct_flags = resp->data.auth.info3.acct_flags;
93 memcpy(i->user_session_key,
94 resp->data.auth.user_session_key,
95 sizeof(i->user_session_key));
96 memcpy(i->lm_session_key,
97 resp->data.auth.first_8_lm_hash,
98 sizeof(i->lm_session_key));
100 i->logon_count = resp->data.auth.info3.logon_count;
101 i->bad_password_count = resp->data.auth.info3.bad_pw_count;
103 i->logon_time = resp->data.auth.info3.logon_time;
104 i->logoff_time = resp->data.auth.info3.logoff_time;
105 i->kickoff_time = resp->data.auth.info3.kickoff_time;
106 i->pass_last_set_time = resp->data.auth.info3.pass_last_set_time;
107 i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time;
108 i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;
110 i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv);
111 BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
112 i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script);
113 BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
114 i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path);
115 BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
116 i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir);
117 BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
118 i->home_drive = talloc_strdup(i, resp->data.auth.info3.dir_drive);
119 BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);
122 i->num_sids += resp->data.auth.info3.num_groups;
123 i->num_sids += resp->data.auth.info3.num_other_sids;
125 i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
126 BAIL_ON_PTR_ERROR(i->sids, wbc_status);
128 wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
130 BAIL_ON_WBC_ERROR(wbc_status);
132 #define _SID_COMPOSE(s, d, r, a) { \
134 if ((s).sid.num_auths < MAXSUBAUTHS) { \
135 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
137 wbc_status = WBC_ERR_INVALID_SID; \
138 BAIL_ON_WBC_ERROR(wbc_status); \
140 (s).attributes = a; \
144 _SID_COMPOSE(i->sids[sn], domain_sid,
145 resp->data.auth.info3.user_rid,
148 _SID_COMPOSE(i->sids[sn], domain_sid,
149 resp->data.auth.info3.group_rid,
153 p = resp->extra_data.data;
155 wbc_status = WBC_INVALID_RESPONSE;
156 BAIL_ON_WBC_ERROR(wbc_status);
159 for (j=0; j < resp->data.auth.info3.num_groups; j++) {
164 char *e = strchr(p, '\n');
166 wbc_status = WBC_INVALID_RESPONSE;
167 BAIL_ON_WBC_ERROR(wbc_status);
172 ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
174 wbc_status = WBC_INVALID_RESPONSE;
175 BAIL_ON_WBC_ERROR(wbc_status);
178 _SID_COMPOSE(i->sids[sn], domain_sid,
183 for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
188 char *e = strchr(p, '\n');
190 wbc_status = WBC_INVALID_RESPONSE;
191 BAIL_ON_WBC_ERROR(wbc_status);
198 wbc_status = WBC_INVALID_RESPONSE;
199 BAIL_ON_WBC_ERROR(wbc_status);
204 ret = sscanf(a, "0x%08X",
207 wbc_status = WBC_INVALID_RESPONSE;
208 BAIL_ON_WBC_ERROR(wbc_status);
211 wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
212 BAIL_ON_WBC_ERROR(wbc_status);
214 i->sids[sn].attributes = attrs;
227 static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx,
228 const struct winbindd_response *resp,
229 struct wbcAuthErrorInfo **_e)
231 wbcErr wbc_status = WBC_ERR_SUCCESS;
232 struct wbcAuthErrorInfo *e;
234 e = talloc(mem_ctx, struct wbcAuthErrorInfo);
235 BAIL_ON_PTR_ERROR(e, wbc_status);
237 e->nt_status = resp->data.auth.nt_status;
238 e->pam_error = resp->data.auth.pam_error;
239 e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string);
240 BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);
242 e->display_string = talloc_strdup(e, resp->data.auth.error_string);
243 BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
253 /** @brief Authenticate with more detailed information
255 * @param params Input parameters, only WBC_AUTH_USER_LEVEL_RESPONSE
257 * @param info Output details on WBC_ERR_SUCCESS
258 * @param error Output details on WBC_ERR_AUTH_ERROR
263 wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
264 struct wbcAuthUserInfo **info,
265 struct wbcAuthErrorInfo **error)
267 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
269 struct winbindd_request request;
270 struct winbindd_response response;
272 ZERO_STRUCT(request);
273 ZERO_STRUCT(response);
280 wbc_status = WBC_ERR_INVALID_PARAM;
281 BAIL_ON_WBC_ERROR(wbc_status);
284 if (!params->account_name) {
285 wbc_status = WBC_ERR_INVALID_PARAM;
286 BAIL_ON_WBC_ERROR(wbc_status);
289 /* Initialize request */
291 switch (params->level) {
292 case WBC_AUTH_USER_LEVEL_PLAIN:
293 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
294 BAIL_ON_WBC_ERROR(wbc_status);
297 case WBC_AUTH_USER_LEVEL_HASH:
298 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
299 BAIL_ON_WBC_ERROR(wbc_status);
302 case WBC_AUTH_USER_LEVEL_RESPONSE:
303 cmd = WINBINDD_PAM_AUTH_CRAP;
304 request.flags = WBFLAG_PAM_INFO3_TEXT |
305 WBFLAG_PAM_USER_SESSION_KEY |
308 if (params->password.response.lm_length &&
309 params->password.response.lm_data) {
310 wbc_status = WBC_ERR_INVALID_PARAM;
311 BAIL_ON_WBC_ERROR(wbc_status);
313 if (params->password.response.lm_length == 0 &&
314 params->password.response.lm_data) {
315 wbc_status = WBC_ERR_INVALID_PARAM;
316 BAIL_ON_WBC_ERROR(wbc_status);
319 if (params->password.response.nt_length &&
320 !params->password.response.nt_data) {
321 wbc_status = WBC_ERR_INVALID_PARAM;
322 BAIL_ON_WBC_ERROR(wbc_status);
324 if (params->password.response.nt_length == 0&&
325 params->password.response.nt_data) {
326 wbc_status = WBC_ERR_INVALID_PARAM;
327 BAIL_ON_WBC_ERROR(wbc_status);
330 strncpy(request.data.auth_crap.user,
331 params->account_name,
332 sizeof(request.data.auth_crap.user)-1);
333 if (params->domain_name) {
334 strncpy(request.data.auth_crap.domain,
336 sizeof(request.data.auth_crap.domain)-1);
338 if (params->workstation_name) {
339 strncpy(request.data.auth_crap.workstation,
340 params->workstation_name,
341 sizeof(request.data.auth_crap.workstation)-1);
344 request.data.auth_crap.logon_parameters =
345 params->parameter_control;
347 memcpy(request.data.auth_crap.chal,
348 params->password.response.challenge,
349 sizeof(request.data.auth_crap.chal));
351 request.data.auth_crap.lm_resp_len =
352 MIN(params->password.response.lm_length,
353 sizeof(request.data.auth_crap.lm_resp));
354 request.data.auth_crap.nt_resp_len =
355 MIN(params->password.response.nt_length,
356 sizeof(request.data.auth_crap.nt_resp));
357 if (params->password.response.lm_data) {
358 memcpy(request.data.auth_crap.lm_resp,
359 params->password.response.lm_data,
360 request.data.auth_crap.lm_resp_len);
362 if (params->password.response.nt_data) {
363 memcpy(request.data.auth_crap.nt_resp,
364 params->password.response.nt_data,
365 request.data.auth_crap.nt_resp_len);
371 wbc_status = WBC_ERR_INVALID_PARAM;
372 BAIL_ON_WBC_ERROR(wbc_status);
375 wbc_status = wbcRequestResponse(cmd,
378 if (response.data.auth.nt_status != 0) {
380 wbc_status = wbc_create_error_info(NULL,
383 BAIL_ON_WBC_ERROR(wbc_status);
386 wbc_status = WBC_ERR_AUTH_ERROR;
387 BAIL_ON_WBC_ERROR(wbc_status);
389 BAIL_ON_WBC_ERROR(wbc_status);
392 wbc_status = wbc_create_auth_info(NULL,
395 BAIL_ON_WBC_ERROR(wbc_status);