root/source4/auth/ntlm/auth_unix.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. authunix_make_server_info
  2. talloc_getpwnam
  3. smb_pam_conv
  4. smb_pam_start
  5. smb_pam_end
  6. smb_pam_auth
  7. smb_pam_account
  8. smb_pam_setcred
  9. check_unix_password
  10. password_check
  11. check_unix_password
  12. authunix_want_check
  13. authunix_check_password
  14. auth_unix_init

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

/* [<][>][^][v][top][bottom][index][help] */