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
);