1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Bartlett 2001
5 Copyright (C) Jeremy Allison 2001
6 Copyright (C) Simo Sorce 2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program 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
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "auth/ntlm/auth_proto.h"
25 #include "system/passwd.h" /* needed by some systems for struct passwd */
26 #include "lib/socket/socket.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "param/param.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_AUTH
33
34 _PUBLIC_ NTSTATUS auth4_unix_init(TALLOC_CTX *);
35
36 /* TODO: look at how to best fill in parms retrieveing a struct passwd info
37 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set
38 */
authunix_make_user_info_dc(TALLOC_CTX * mem_ctx,const char * netbios_name,const struct auth_usersupplied_info * user_info,struct passwd * pwd,struct auth_user_info_dc ** _user_info_dc)39 static NTSTATUS authunix_make_user_info_dc(TALLOC_CTX *mem_ctx,
40 const char *netbios_name,
41 const struct auth_usersupplied_info *user_info,
42 struct passwd *pwd,
43 struct auth_user_info_dc **_user_info_dc)
44 {
45 struct auth_user_info_dc *user_info_dc;
46 struct auth_user_info *info;
47 NTSTATUS status;
48
49 /* This is a real, real hack */
50 if (pwd->pw_uid == 0) {
51 status = auth_system_user_info_dc(mem_ctx, netbios_name, &user_info_dc);
52 if (!NT_STATUS_IS_OK(status)) {
53 return status;
54 }
55
56 user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
57 NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
58
59 info->account_name = talloc_steal(info, pwd->pw_name);
60 NT_STATUS_HAVE_NO_MEMORY(info->account_name);
61
62 info->domain_name = talloc_strdup(info, "unix");
63 NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
64 } else {
65 user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
66 NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
67
68 user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
69 NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
70
71 info->authenticated = true;
72
73 info->account_name = talloc_steal(info, pwd->pw_name);
74 NT_STATUS_HAVE_NO_MEMORY(info->account_name);
75
76 info->domain_name = talloc_strdup(info, "unix");
77 NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
78
79 /* This isn't in any way correct.. */
80 user_info_dc->num_sids = 0;
81 user_info_dc->sids = NULL;
82 }
83 user_info_dc->user_session_key = data_blob(NULL,0);
84 user_info_dc->lm_session_key = data_blob(NULL,0);
85
86 info->full_name = talloc_steal(info, pwd->pw_gecos);
87 NT_STATUS_HAVE_NO_MEMORY(info->full_name);
88 info->logon_script = talloc_strdup(info, "");
89 NT_STATUS_HAVE_NO_MEMORY(info->logon_script);
90 info->profile_path = talloc_strdup(info, "");
91 NT_STATUS_HAVE_NO_MEMORY(info->profile_path);
92 info->home_directory = talloc_strdup(info, "");
93 NT_STATUS_HAVE_NO_MEMORY(info->home_directory);
94 info->home_drive = talloc_strdup(info, "");
95 NT_STATUS_HAVE_NO_MEMORY(info->home_drive);
96
97 info->last_logon = 0;
98 info->last_logoff = 0;
99 info->acct_expiry = 0;
100 info->last_password_change = 0;
101 info->allow_password_change = 0;
102 info->force_password_change = 0;
103 info->logon_count = 0;
104 info->bad_password_count = 0;
105 info->acct_flags = 0;
106
107 *_user_info_dc = user_info_dc;
108
109 return NT_STATUS_OK;
110 }
111
talloc_getpwnam(TALLOC_CTX * ctx,const char * username,struct passwd ** pws)112 static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws)
113 {
114 struct passwd *ret;
115 struct passwd *from;
116
117 *pws = NULL;
118
119 ret = talloc(ctx, struct passwd);
120 NT_STATUS_HAVE_NO_MEMORY(ret);
121
122 from = getpwnam(username);
123 if (!from) {
124 return NT_STATUS_NO_SUCH_USER;
125 }
126
127 ret->pw_name = talloc_strdup(ctx, from->pw_name);
128 NT_STATUS_HAVE_NO_MEMORY(ret->pw_name);
129
130 ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd);
131 NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd);
132
133 ret->pw_uid = from->pw_uid;
134 ret->pw_gid = from->pw_gid;
135 ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos);
136 NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos);
137
138 ret->pw_dir = talloc_strdup(ctx, from->pw_dir);
139 NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir);
140
141 ret->pw_shell = talloc_strdup(ctx, from->pw_shell);
142 NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell);
143
144 *pws = ret;
145
146 return NT_STATUS_OK;
147 }
148
149
150 #ifdef HAVE_SECURITY_PAM_APPL_H
151 #include <security/pam_appl.h>
152
153 struct smb_pam_user_info {
154 const char *account_name;
155 const char *plaintext_password;
156 };
157
158 #define COPY_STRING(s) (s) ? strdup(s) : NULL
159
160 /*
161 * Check user password
162 * Currently it uses PAM only and fails on systems without PAM
163 * Samba3 code located in pass_check.c is to ugly to be used directly it will
164 * need major rework that's why pass_check.c is still there.
165 */
166
smb_pam_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** reply,void * appdata_ptr)167 static int smb_pam_conv(int num_msg, const struct pam_message **msg,
168 struct pam_response **reply, void *appdata_ptr)
169 {
170 struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr;
171 int num;
172
173 if (num_msg <= 0) {
174 *reply = NULL;
175 return PAM_CONV_ERR;
176 }
177
178 /*
179 * Apparantly HPUX has a buggy PAM that doesn't support the
180 * data pointer. Fail if this is the case. JRA.
181 */
182
183 if (info == NULL) {
184 *reply = NULL;
185 return PAM_CONV_ERR;
186 }
187
188 /*
189 * PAM frees memory in reply messages by itself
190 * so use malloc instead of talloc here.
191 */
192 *reply = malloc_array_p(struct pam_response, num_msg);
193 if (*reply == NULL) {
194 return PAM_CONV_ERR;
195 }
196
197 for (num = 0; num < num_msg; num++) {
198 switch (msg[num]->msg_style) {
199 case PAM_PROMPT_ECHO_ON:
200 (*reply)[num].resp_retcode = PAM_SUCCESS;
201 (*reply)[num].resp = COPY_STRING(info->account_name);
202 break;
203
204 case PAM_PROMPT_ECHO_OFF:
205 (*reply)[num].resp_retcode = PAM_SUCCESS;
206 (*reply)[num].resp = COPY_STRING(info->plaintext_password);
207 break;
208
209 case PAM_TEXT_INFO:
210 (*reply)[num].resp_retcode = PAM_SUCCESS;
211 (*reply)[num].resp = NULL;
212 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg)));
213 break;
214
215 case PAM_ERROR_MSG:
216 (*reply)[num].resp_retcode = PAM_SUCCESS;
217 (*reply)[num].resp = NULL;
218 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg)));
219 break;
220
221 default:
222 while (num > 0) {
223 SAFE_FREE((*reply)[num-1].resp);
224 num--;
225 }
226 SAFE_FREE(*reply);
227 *reply = NULL;
228 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n"));
229 return PAM_CONV_ERR;
230 }
231 }
232
233 return PAM_SUCCESS;
234 }
235
236 /*
237 * Start PAM authentication for specified account
238 */
239
smb_pam_start(pam_handle_t ** pamh,const char * account_name,const char * remote_host,struct pam_conv * pconv)240 static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv)
241 {
242 int pam_error;
243
244 if (account_name == NULL || remote_host == NULL) {
245 return NT_STATUS_INVALID_PARAMETER;
246 }
247
248 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name));
249
250 pam_error = pam_start("samba", account_name, pconv, pamh);
251 if (pam_error != PAM_SUCCESS) {
252 /* no valid pamh here, can we reliably call pam_strerror ? */
253 DEBUG(4,("smb_pam_start: pam_start failed!\n"));
254 return NT_STATUS_UNSUCCESSFUL;
255 }
256
257 #ifdef PAM_RHOST
258 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host));
259 pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host);
260 if (pam_error != PAM_SUCCESS) {
261 NTSTATUS nt_status;
262
263 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n",
264 pam_strerror(*pamh, pam_error)));
265 nt_status = pam_to_nt_status(pam_error);
266
267 pam_error = pam_end(*pamh, 0);
268 if (pam_error != PAM_SUCCESS) {
269 /* no valid pamh here, can we reliably call pam_strerror ? */
270 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
271 pam_error));
272 return pam_to_nt_status(pam_error);
273 }
274 return nt_status;
275 }
276 #endif
277 #ifdef PAM_TTY
278 DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
279 pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
280 if (pam_error != PAM_SUCCESS) {
281 NTSTATUS nt_status;
282
283 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n",
284 pam_strerror(*pamh, pam_error)));
285 nt_status = pam_to_nt_status(pam_error);
286
287 pam_error = pam_end(*pamh, 0);
288 if (pam_error != PAM_SUCCESS) {
289 /* no valid pamh here, can we reliably call pam_strerror ? */
290 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n",
291 pam_error));
292 return pam_to_nt_status(pam_error);
293 }
294 return nt_status;
295 }
296 #endif
297 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name));
298
299 return NT_STATUS_OK;
300 }
301
smb_pam_end(pam_handle_t * pamh)302 static NTSTATUS smb_pam_end(pam_handle_t *pamh)
303 {
304 int pam_error;
305
306 if (pamh != NULL) {
307 pam_error = pam_end(pamh, 0);
308 if (pam_error != PAM_SUCCESS) {
309 /* no valid pamh here, can we reliably call pam_strerror ? */
310 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n",
311 pam_error));
312 return pam_to_nt_status(pam_error);
313 }
314 return NT_STATUS_OK;
315 }
316
317 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n"));
318 return NT_STATUS_UNSUCCESSFUL;
319 }
320
321 /*
322 * PAM Authentication Handler
323 */
smb_pam_auth(pam_handle_t * pamh,bool allow_null_passwords,const char * user)324 static NTSTATUS smb_pam_auth(pam_handle_t *pamh, bool allow_null_passwords, const char *user)
325 {
326 int pam_error;
327
328 /*
329 * To enable debugging set in /etc/pam.d/samba:
330 * auth required /lib/security/pam_pwdb.so nullok shadow audit
331 */
332
333 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
334
335 pam_error = pam_authenticate(pamh, PAM_SILENT | (allow_null_passwords ? 0 : PAM_DISALLOW_NULL_AUTHTOK));
336 switch( pam_error ){
337 case PAM_AUTH_ERR:
338 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
339 break;
340 case PAM_CRED_INSUFFICIENT:
341 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
342 break;
343 case PAM_AUTHINFO_UNAVAIL:
344 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
345 break;
346 case PAM_USER_UNKNOWN:
347 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
348 break;
349 case PAM_MAXTRIES:
350 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
351 break;
352 case PAM_ABORT:
353 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
354 break;
355 case PAM_SUCCESS:
356 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
357 break;
358 default:
359 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
360 break;
361 }
362
363 return pam_to_nt_status(pam_error);
364 }
365
366 /*
367 * PAM Account Handler
368 */
smb_pam_account(pam_handle_t * pamh,const char * user)369 static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
370 {
371 int pam_error;
372
373 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
374
375 pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
376 switch( pam_error ) {
377 case PAM_AUTHTOK_EXPIRED:
378 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
379 break;
380 case PAM_ACCT_EXPIRED:
381 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
382 break;
383 case PAM_AUTH_ERR:
384 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
385 break;
386 case PAM_PERM_DENIED:
387 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
388 break;
389 case PAM_USER_UNKNOWN:
390 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
391 break;
392 case PAM_SUCCESS:
393 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
394 break;
395 default:
396 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
397 break;
398 }
399
400 return pam_to_nt_status(pam_error);
401 }
402
403 /*
404 * PAM Credential Setting
405 */
406
smb_pam_setcred(pam_handle_t * pamh,const char * user)407 static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
408 {
409 int pam_error;
410
411 /*
412 * This will allow samba to aquire a kerberos token. And, when
413 * exporting an AFS cell, be able to /write/ to this cell.
414 */
415
416 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
417
418 pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT));
419 switch( pam_error ) {
420 case PAM_CRED_UNAVAIL:
421 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
422 break;
423 case PAM_CRED_EXPIRED:
424 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
425 break;
426 case PAM_USER_UNKNOWN:
427 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
428 break;
429 case PAM_CRED_ERR:
430 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
431 break;
432 case PAM_SUCCESS:
433 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
434 break;
435 default:
436 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
437 break;
438 }
439
440 return pam_to_nt_status(pam_error);
441 }
442
check_unix_password(TALLOC_CTX * ctx,struct loadparm_context * lp_ctx,const struct auth_usersupplied_info * user_info,struct passwd ** pws)443 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
444 const struct auth_usersupplied_info *user_info, struct passwd **pws)
445 {
446 struct smb_pam_user_info *info;
447 struct pam_conv *pamconv;
448 pam_handle_t *pamh;
449 NTSTATUS nt_status;
450
451 info = talloc(ctx, struct smb_pam_user_info);
452 if (info == NULL) {
453 return NT_STATUS_NO_MEMORY;
454 }
455
456 info->account_name = user_info->mapped.account_name;
457 info->plaintext_password = user_info->password.plaintext;
458
459 pamconv = talloc(ctx, struct pam_conv);
460 if (pamconv == NULL) {
461 return NT_STATUS_NO_MEMORY;
462 }
463
464 pamconv->conv = smb_pam_conv;
465 pamconv->appdata_ptr = (void *)info;
466
467 /* TODO:
468 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME
469 * if true set up a crack name routine.
470 */
471
472 nt_status = smb_pam_start(&pamh, user_info->mapped.account_name,
473 user_info->remote_host ? tsocket_address_inet_addr_string(user_info->remote_host, ctx) : NULL, pamconv);
474 if (!NT_STATUS_IS_OK(nt_status)) {
475 return nt_status;
476 }
477
478 nt_status = smb_pam_auth(pamh, lpcfg_null_passwords(lp_ctx), user_info->mapped.account_name);
479 if (!NT_STATUS_IS_OK(nt_status)) {
480 smb_pam_end(pamh);
481 return nt_status;
482 }
483
484 if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) {
485
486 nt_status = smb_pam_account(pamh, user_info->mapped.account_name);
487 if (!NT_STATUS_IS_OK(nt_status)) {
488 smb_pam_end(pamh);
489 return nt_status;
490 }
491
492 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name);
493 if (!NT_STATUS_IS_OK(nt_status)) {
494 smb_pam_end(pamh);
495 return nt_status;
496 }
497 }
498
499 smb_pam_end(pamh);
500
501 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws);
502 if (!NT_STATUS_IS_OK(nt_status)) {
503 return nt_status;
504 }
505
506 return NT_STATUS_OK;
507 }
508
509 #else
510
511 /****************************************************************************
512 core of password checking routine
513 ****************************************************************************/
password_check(const char * username,const char * password,const char * crypted,const char * salt)514 static NTSTATUS password_check(const char *username, const char *password,
515 const char *crypted, const char *salt)
516 {
517 bool ret;
518
519
520
521 #ifdef OSF1_ENH_SEC
522
523 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0);
524
525 if (!ret) {
526 DEBUG(2,
527 ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
528 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
529 }
530 if (ret) {
531 return NT_STATUS_OK;
532 } else {
533 return NT_STATUS_WRONG_PASSWORD;
534 }
535
536 #endif /* OSF1_ENH_SEC */
537
538 #ifdef ULTRIX_AUTH
539 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0);
540 if (ret) {
541 return NT_STATUS_OK;
542 } else {
543 return NT_STATUS_WRONG_PASSWORD;
544 }
545
546 #endif /* ULTRIX_AUTH */
547
548
549
550 #ifdef HAVE_BIGCRYPT
551 ret = (strcmp(bigcrypt(password, salt), crypted) == 0);
552 if (ret) {
553 return NT_STATUS_OK;
554 } else {
555 return NT_STATUS_WRONG_PASSWORD;
556 }
557 #endif /* HAVE_BIGCRYPT */
558
559 #ifndef HAVE_CRYPT
560 DEBUG(1, ("Warning - no crypt available\n"));
561 return NT_STATUS_LOGON_FAILURE;
562 #else /* HAVE_CRYPT */
563 ret = (strcmp((char *)crypt(password, salt), crypted) == 0);
564 if (ret) {
565 return NT_STATUS_OK;
566 } else {
567 return NT_STATUS_WRONG_PASSWORD;
568 }
569 #endif /* HAVE_CRYPT */
570 }
571
check_unix_password(TALLOC_CTX * ctx,struct loadparm_context * lp_ctx,const struct auth_usersupplied_info * user_info,struct passwd ** ret_passwd)572 static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx,
573 const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd)
574 {
575 char *username;
576 char *password;
577 char *salt;
578 char *crypted;
579 struct passwd *pws;
580 NTSTATUS nt_status;
581
582 *ret_passwd = NULL;
583
584 username = talloc_strdup(ctx, user_info->mapped.account_name);
585 password = talloc_strdup(ctx, user_info->password.plaintext);
586
587 nt_status = talloc_getpwnam(ctx, username, &pws);
588 if (!NT_STATUS_IS_OK(nt_status)) {
589 return nt_status;
590 }
591
592 crypted = pws->pw_passwd;
593 salt = pws->pw_passwd;
594
595 #ifdef HAVE_GETSPNAM
596 {
597 struct spwd *spass;
598
599 /* many shadow systems require you to be root to get
600 the password, in most cases this should already be
601 the case when this function is called, except
602 perhaps for IPC password changing requests */
603
604 spass = getspnam(pws->pw_name);
605 if (spass && spass->sp_pwdp) {
606 crypted = talloc_strdup(ctx, spass->sp_pwdp);
607 NT_STATUS_HAVE_NO_MEMORY(crypted);
608 salt = talloc_strdup(ctx, spass->sp_pwdp);
609 NT_STATUS_HAVE_NO_MEMORY(salt);
610 }
611 }
612 #elif defined(IA_UINFO)
613 {
614 char *ia_password;
615 /* Need to get password with SVR4.2's ia_ functions
616 instead of get{sp,pw}ent functions. Required by
617 UnixWare 2.x, tested on version
618 2.1. (tangent@cyberport.com) */
619 uinfo_t uinfo;
620 if (ia_openinfo(pws->pw_name, &uinfo) != -1) {
621 ia_get_logpwd(uinfo, &ia_password);
622 crypted = talloc_strdup(ctx, ia_password);
623 NT_STATUS_HAVE_NO_MEMORY(crypted);
624 }
625 }
626 #endif
627
628
629 #ifdef HAVE_GETPWANAM
630 {
631 struct passwd_adjunct *pwret;
632 pwret = getpwanam(s);
633 if (pwret && pwret->pwa_passwd) {
634 crypted = talloc_strdup(ctx, pwret->pwa_passwd);
635 NT_STATUS_HAVE_NO_MEMORY(crypted);
636 }
637 }
638 #endif
639
640 #ifdef OSF1_ENH_SEC
641 {
642 struct pr_passwd *mypasswd;
643 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username));
644 mypasswd = getprpwnam(username);
645 if (mypasswd) {
646 username = talloc_strdup(ctx, mypasswd->ufld.fd_name);
647 NT_STATUS_HAVE_NO_MEMORY(username);
648 crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt);
649 NT_STATUS_HAVE_NO_MEMORY(crypted);
650 } else {
651 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username));
652 }
653 }
654 #endif
655
656 #ifdef ULTRIX_AUTH
657 {
658 AUTHORIZATION *ap = getauthuid(pws->pw_uid);
659 if (ap) {
660 crypted = talloc_strdup(ctx, ap->a_password);
661 endauthent();
662 NT_STATUS_HAVE_NO_MEMORY(crypted);
663 }
664 }
665 #endif
666
667
668 if (crypted[0] == '\0') {
669 if (!lpcfg_null_passwords(lp_ctx)) {
670 DEBUG(2, ("Disallowing %s with null password\n", username));
671 return NT_STATUS_LOGON_FAILURE;
672 }
673 if (password == NULL) {
674 DEBUG(3, ("Allowing access to %s with null password\n", username));
675 *ret_passwd = pws;
676 return NT_STATUS_OK;
677 }
678 }
679
680 /* try it as it came to us */
681 nt_status = password_check(username, password, crypted, salt);
682 if (NT_STATUS_IS_OK(nt_status)) {
683 *ret_passwd = pws;
684 return nt_status;
685 }
686 else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
687 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
688 return nt_status;
689 }
690
691 /* we no longer try different case combinations here. The use
692 * of this code is now web auth, where trying different case
693 * combinations makes no sense
694 */
695
696 return NT_STATUS_WRONG_PASSWORD;
697 }
698
699 #endif
700
701 /** Check a plaintext username/password
702 *
703 **/
704
authunix_want_check(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info)705 static NTSTATUS authunix_want_check(struct auth_method_context *ctx,
706 TALLOC_CTX *mem_ctx,
707 const struct auth_usersupplied_info *user_info)
708 {
709 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
710 return NT_STATUS_NOT_IMPLEMENTED;
711 }
712
713 return NT_STATUS_OK;
714 }
715
authunix_check_password(struct auth_method_context * ctx,TALLOC_CTX * mem_ctx,const struct auth_usersupplied_info * user_info,struct auth_user_info_dc ** user_info_dc,bool * authoritative)716 static NTSTATUS authunix_check_password(struct auth_method_context *ctx,
717 TALLOC_CTX *mem_ctx,
718 const struct auth_usersupplied_info *user_info,
719 struct auth_user_info_dc **user_info_dc,
720 bool *authoritative)
721 {
722 TALLOC_CTX *check_ctx;
723 NTSTATUS nt_status;
724 struct passwd *pwd;
725
726 if (user_info->password_state != AUTH_PASSWORD_PLAIN) {
727 return NT_STATUS_INVALID_PARAMETER;
728 }
729
730 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password");
731 if (check_ctx == NULL) {
732 return NT_STATUS_NO_MEMORY;
733 }
734
735 nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd);
736 if (!NT_STATUS_IS_OK(nt_status)) {
737 talloc_free(check_ctx);
738 return nt_status;
739 }
740
741 nt_status = authunix_make_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
742 user_info, pwd, user_info_dc);
743 if (!NT_STATUS_IS_OK(nt_status)) {
744 talloc_free(check_ctx);
745 return nt_status;
746 }
747
748 talloc_free(check_ctx);
749 return NT_STATUS_OK;
750 }
751
752 static const struct auth_operations unix_ops = {
753 .name = "unix",
754 .want_check = authunix_want_check,
755 .check_password = authunix_check_password
756 };
757
auth4_unix_init(TALLOC_CTX * ctx)758 _PUBLIC_ NTSTATUS auth4_unix_init(TALLOC_CTX *ctx)
759 {
760 NTSTATUS ret;
761
762 ret = auth_register(ctx, &unix_ops);
763 if (!NT_STATUS_IS_OK(ret)) {
764 DEBUG(0,("Failed to register unix auth backend!\n"));
765 return ret;
766 }
767
768 return ret;
769 }
770