LCOV - code coverage report
Current view: top level - source3/auth - pampass.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 16 432 3.7 %
Date: 2021-09-23 10:06:22 Functions: 3 24 12.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    PAM Password checking
       4             :    Copyright (C) Andrew Tridgell 1992-2001
       5             :    Copyright (C) John H Terpsta 1999-2001
       6             :    Copyright (C) Andrew Bartlett 2001
       7             :    Copyright (C) Jeremy Allison 2001
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : /*
      24             :  * This module provides PAM based functions for validation of
      25             :  * username/password pairs, account managment, session and access control.
      26             :  * Note: SMB password checking is done in smbpass.c
      27             :  */
      28             : 
      29             : #include "includes.h"
      30             : #include "auth.h"
      31             : #include "../libcli/auth/pam_errors.h"
      32             : #include "lib/util/string_wrappers.h"
      33             : 
      34             : #undef DBGC_CLASS
      35             : #define DBGC_CLASS DBGC_AUTH
      36             : 
      37             : #ifdef WITH_PAM
      38             : 
      39             : /*******************************************************************
      40             :  * Handle PAM authentication 
      41             :  *      - Access, Authentication, Session, Password
      42             :  *   Note: See PAM Documentation and refer to local system PAM implementation
      43             :  *   which determines what actions/limitations/allowances become affected.
      44             :  *********************************************************************/
      45             : 
      46             : #if defined(HAVE_SECURITY_PAM_APPL_H)
      47             : #include <security/pam_appl.h>
      48             : #elif defined(HAVE_PAM_PAM_APPL_H)
      49             : #include <pam/pam_appl.h>
      50             : #endif
      51             : 
      52             : /*
      53             :  * Structure used to communicate between the conversation function
      54             :  * and the server_login/change password functions.
      55             :  */
      56             : 
      57             : struct smb_pam_userdata {
      58             :         const char *PAM_username;
      59             :         const char *PAM_password;
      60             :         const char *PAM_newpassword;
      61             : };
      62             : 
      63             : typedef int (*smb_pam_conv_fn)(int, const struct pam_message **, struct pam_response **, void *appdata_ptr);
      64             : 
      65           0 : static char *smb_pam_copy_string(const char *s)
      66             : {
      67           0 :         if (s == NULL) {
      68           0 :                 return NULL;
      69             :         }
      70           0 :         return SMB_STRDUP(s);
      71             : }
      72             : 
      73           0 : static char *smb_pam_copy_fstring(const char *s)
      74             : {
      75           0 :         if (s[0] == '\0') {
      76           0 :                 return NULL;
      77             :         }
      78           0 :         return SMB_STRDUP(s);
      79             : }
      80             : 
      81             : /*******************************************************************
      82             :  PAM error handler.
      83             :  *********************************************************************/
      84             : 
      85           0 : static bool smb_pam_error_handler(pam_handle_t *pamh, int pam_error, const char *msg, int dbglvl)
      86             : {
      87             : 
      88           0 :         if( pam_error != PAM_SUCCESS) {
      89           0 :                 DEBUG(dbglvl, ("smb_pam_error_handler: PAM: %s : %s\n",
      90             :                                 msg, pam_strerror(pamh, pam_error)));
      91           0 :                 return False;
      92             :         }
      93           0 :         return True;
      94             : }
      95             : 
      96             : /*******************************************************************
      97             :  This function is a sanity check, to make sure that we NEVER report
      98             :  failure as sucess.
      99             : *********************************************************************/
     100             : 
     101           0 : static bool smb_pam_nt_status_error_handler(pam_handle_t *pamh, int pam_error,
     102             :                                             const char *msg, int dbglvl, 
     103             :                                             NTSTATUS *nt_status)
     104             : {
     105           0 :         *nt_status = pam_to_nt_status(pam_error);
     106             : 
     107           0 :         if (smb_pam_error_handler(pamh, pam_error, msg, dbglvl))
     108           0 :                 return True;
     109             : 
     110           0 :         if (NT_STATUS_IS_OK(*nt_status)) {
     111             :                 /* Complain LOUDLY */
     112           0 :                 DEBUG(0, ("smb_pam_nt_status_error_handler: PAM: BUG: PAM and NT_STATUS \
     113             : error MISMATCH, forcing to NT_STATUS_LOGON_FAILURE"));
     114           0 :                 *nt_status = NT_STATUS_LOGON_FAILURE;
     115             :         }
     116           0 :         return False;
     117             : }
     118             : 
     119             : /*
     120             :  * PAM conversation function
     121             :  * Here we assume (for now, at least) that echo on means login name, and
     122             :  * echo off means password.
     123             :  */
     124             : 
     125           0 : static int smb_pam_conv(int num_msg,
     126             :                     const struct pam_message **msg,
     127             :                     struct pam_response **resp,
     128             :                     void *appdata_ptr)
     129             : {
     130           0 :         int replies = 0;
     131           0 :         struct pam_response *reply = NULL;
     132           0 :         struct smb_pam_userdata *udp = (struct smb_pam_userdata *)appdata_ptr;
     133             : 
     134           0 :         *resp = NULL;
     135             : 
     136           0 :         if (num_msg <= 0)
     137           0 :                 return PAM_CONV_ERR;
     138             : 
     139             :         /*
     140             :          * Apparantly HPUX has a buggy PAM that doesn't support the
     141             :          * appdata_ptr. Fail if this is the case. JRA.
     142             :          */
     143             : 
     144           0 :         if (udp == NULL) {
     145           0 :                 DEBUG(0,("smb_pam_conv: PAM on this system is broken - appdata_ptr == NULL !\n"));
     146           0 :                 return PAM_CONV_ERR;
     147             :         }
     148             : 
     149           0 :         reply = SMB_MALLOC_ARRAY(struct pam_response, num_msg);
     150           0 :         if (!reply)
     151           0 :                 return PAM_CONV_ERR;
     152             : 
     153           0 :         memset(reply, '\0', sizeof(struct pam_response) * num_msg);
     154             : 
     155           0 :         for (replies = 0; replies < num_msg; replies++) {
     156           0 :                 switch (msg[replies]->msg_style) {
     157           0 :                         case PAM_PROMPT_ECHO_ON:
     158           0 :                                 reply[replies].resp_retcode = PAM_SUCCESS;
     159           0 :                                 reply[replies].resp = smb_pam_copy_string(
     160             :                                         udp->PAM_username);
     161             :                                 /* PAM frees resp */
     162           0 :                                 break;
     163             : 
     164           0 :                         case PAM_PROMPT_ECHO_OFF:
     165           0 :                                 reply[replies].resp_retcode = PAM_SUCCESS;
     166           0 :                                 reply[replies].resp = smb_pam_copy_string(
     167             :                                         udp->PAM_password);
     168             :                                 /* PAM frees resp */
     169           0 :                                 break;
     170             : 
     171           0 :                         case PAM_TEXT_INFO:
     172             :                                 FALL_THROUGH;
     173             : 
     174             :                         case PAM_ERROR_MSG:
     175             :                                 /* ignore it... */
     176           0 :                                 reply[replies].resp_retcode = PAM_SUCCESS;
     177           0 :                                 reply[replies].resp = NULL;
     178           0 :                                 break;
     179             : 
     180           0 :                         default:
     181             :                                 /* Must be an error of some sort... */
     182           0 :                                 SAFE_FREE(reply);
     183           0 :                                 return PAM_CONV_ERR;
     184             :                 }
     185             :         }
     186           0 :         if (reply)
     187           0 :                 *resp = reply;
     188           0 :         return PAM_SUCCESS;
     189             : }
     190             : 
     191             : /*
     192             :  * PAM password change conversation function
     193             :  * Here we assume (for now, at least) that echo on means login name, and
     194             :  * echo off means password.
     195             :  */
     196             : 
     197           0 : static void special_char_sub(char *buf)
     198             : {
     199           0 :         all_string_sub(buf, "\\n", "", 0);
     200           0 :         all_string_sub(buf, "\\r", "", 0);
     201           0 :         all_string_sub(buf, "\\s", " ", 0);
     202           0 :         all_string_sub(buf, "\\t", "\t", 0);
     203           0 : }
     204             : 
     205           0 : static void pwd_sub(char *buf, const char *username, const char *oldpass, const char *newpass)
     206             : {
     207           0 :         fstring_sub(buf, "%u", username);
     208           0 :         all_string_sub(buf, "%o", oldpass, sizeof(fstring));
     209           0 :         all_string_sub(buf, "%n", newpass, sizeof(fstring));
     210           0 : }
     211             : 
     212             : 
     213             : struct chat_struct {
     214             :         struct chat_struct *next, *prev;
     215             :         fstring prompt;
     216             :         fstring reply;
     217             : };
     218             : 
     219             : /**************************************************************
     220             :  Create a linked list containing chat data.
     221             : ***************************************************************/
     222             : 
     223           0 : static struct chat_struct *make_pw_chat(const char *p) 
     224             : {
     225             :         char *prompt;
     226             :         char *reply;
     227           0 :         struct chat_struct *list = NULL;
     228             :         struct chat_struct *t;
     229           0 :         TALLOC_CTX *frame = talloc_stackframe();
     230             : 
     231             :         while (1) {
     232           0 :                 t = SMB_MALLOC_P(struct chat_struct);
     233           0 :                 if (!t) {
     234           0 :                         DEBUG(0,("make_pw_chat: malloc failed!\n"));
     235           0 :                         TALLOC_FREE(frame);
     236           0 :                         return NULL;
     237             :                 }
     238             : 
     239           0 :                 ZERO_STRUCTP(t);
     240             : 
     241           0 :                 DLIST_ADD_END(list, t);
     242             : 
     243           0 :                 if (!next_token_talloc(frame, &p, &prompt, NULL)) {
     244           0 :                         break;
     245             :                 }
     246             : 
     247           0 :                 if (strequal(prompt,".")) {
     248           0 :                         fstrcpy(prompt,"*");
     249             :                 }
     250             : 
     251           0 :                 special_char_sub(prompt);
     252           0 :                 fstrcpy(t->prompt, prompt);
     253           0 :                 (void)strlower_m(t->prompt);
     254           0 :                 trim_char(t->prompt, ' ', ' ');
     255             : 
     256           0 :                 if (!next_token_talloc(frame, &p, &reply, NULL)) {
     257           0 :                         break;
     258             :                 }
     259             : 
     260           0 :                 if (strequal(reply,".")) {
     261           0 :                         fstrcpy(reply,"");
     262             :                 }
     263             : 
     264           0 :                 special_char_sub(reply);
     265           0 :                 fstrcpy(t->reply, reply);
     266           0 :                 (void)strlower_m(t->reply);
     267           0 :                 trim_char(t->reply, ' ', ' ');
     268             : 
     269             :         }
     270           0 :         TALLOC_FREE(frame);
     271           0 :         return list;
     272             : }
     273             : 
     274           0 : static void free_pw_chat(struct chat_struct *list)
     275             : {
     276           0 :     while (list) {
     277           0 :         struct chat_struct *old_head = list;
     278           0 :         DLIST_REMOVE(list, list);
     279           0 :         SAFE_FREE(old_head);
     280             :     }
     281           0 : }
     282             : 
     283           0 : static int smb_pam_passchange_conv(int num_msg,
     284             :                                 const struct pam_message **msg,
     285             :                                 struct pam_response **resp,
     286             :                                 void *appdata_ptr)
     287             : {
     288           0 :         int replies = 0;
     289           0 :         struct pam_response *reply = NULL;
     290             :         fstring current_prompt;
     291             :         fstring current_reply;
     292           0 :         struct smb_pam_userdata *udp = (struct smb_pam_userdata *)appdata_ptr;
     293             :         struct chat_struct *pw_chat;
     294             :         struct chat_struct *t;
     295           0 :         const struct loadparm_substitution *lp_sub =
     296           0 :                 loadparm_s3_global_substitution();
     297             :         bool found; 
     298           0 :         *resp = NULL;
     299             : 
     300           0 :         DEBUG(10,("smb_pam_passchange_conv: starting converstation for %d messages\n", num_msg));
     301             : 
     302           0 :         if (num_msg <= 0)
     303           0 :                 return PAM_CONV_ERR;
     304             : 
     305           0 :         if ((pw_chat = make_pw_chat(lp_passwd_chat(talloc_tos(), lp_sub))) == NULL)
     306           0 :                 return PAM_CONV_ERR;
     307             : 
     308             :         /*
     309             :          * Apparantly HPUX has a buggy PAM that doesn't support the
     310             :          * appdata_ptr. Fail if this is the case. JRA.
     311             :          */
     312             : 
     313           0 :         if (udp == NULL) {
     314           0 :                 DEBUG(0,("smb_pam_passchange_conv: PAM on this system is broken - appdata_ptr == NULL !\n"));
     315           0 :                 free_pw_chat(pw_chat);
     316           0 :                 return PAM_CONV_ERR;
     317             :         }
     318             : 
     319           0 :         reply = SMB_MALLOC_ARRAY(struct pam_response, num_msg);
     320           0 :         if (!reply) {
     321           0 :                 DEBUG(0,("smb_pam_passchange_conv: malloc for reply failed!\n"));
     322           0 :                 free_pw_chat(pw_chat);
     323           0 :                 return PAM_CONV_ERR;
     324             :         }
     325             : 
     326           0 :         for (replies = 0; replies < num_msg; replies++) {
     327           0 :                 found = False;
     328           0 :                 DEBUG(10,("smb_pam_passchange_conv: Processing message %d\n", replies));
     329           0 :                 switch (msg[replies]->msg_style) {
     330           0 :                 case PAM_PROMPT_ECHO_ON:
     331           0 :                         DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: PAM said: %s\n", msg[replies]->msg));
     332           0 :                         fstrcpy(current_prompt, msg[replies]->msg);
     333           0 :                         trim_char(current_prompt, ' ', ' ');
     334           0 :                         for (t=pw_chat; t; t=t->next) {
     335             : 
     336           0 :                                 DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: trying to match |%s| to |%s|\n",
     337             :                                                 t->prompt, current_prompt ));
     338             : 
     339           0 :                                 if (unix_wild_match(t->prompt, current_prompt)) {
     340           0 :                                         fstrcpy(current_reply, t->reply);
     341           0 :                                         DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: We sent: %s\n", current_reply));
     342           0 :                                         pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword);
     343             : #ifdef DEBUG_PASSWORD
     344           0 :                                         DEBUG(100,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: We actually sent: %s\n", current_reply));
     345             : #endif
     346           0 :                                         reply[replies].resp_retcode = PAM_SUCCESS;
     347           0 :                                         reply[replies].resp = smb_pam_copy_fstring(
     348             :                                                 current_reply);
     349           0 :                                         found = True;
     350           0 :                                         break;
     351             :                                 }
     352             :                         }
     353             :                         /* PAM frees resp */
     354           0 :                         if (!found) {
     355           0 :                                 DEBUG(3,("smb_pam_passchange_conv: Could not find reply for PAM prompt: %s\n",msg[replies]->msg));
     356           0 :                                 free_pw_chat(pw_chat);
     357           0 :                                 SAFE_FREE(reply);
     358           0 :                                 return PAM_CONV_ERR;
     359             :                         }
     360           0 :                         break;
     361             : 
     362           0 :                 case PAM_PROMPT_ECHO_OFF:
     363           0 :                         DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: PAM said: %s\n", msg[replies]->msg));
     364           0 :                         fstrcpy(current_prompt, msg[replies]->msg);
     365           0 :                         trim_char(current_prompt, ' ', ' ');
     366           0 :                         for (t=pw_chat; t; t=t->next) {
     367             : 
     368           0 :                                 DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: trying to match |%s| to |%s|\n",
     369             :                                                 t->prompt, current_prompt ));
     370             : 
     371           0 :                                 if (unix_wild_match(t->prompt, current_prompt)) {
     372           0 :                                         fstrcpy(current_reply, t->reply);
     373           0 :                                         DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: We sent: %s\n", current_reply));
     374           0 :                                         pwd_sub(current_reply, udp->PAM_username, udp->PAM_password, udp->PAM_newpassword);
     375           0 :                                         reply[replies].resp_retcode = PAM_SUCCESS;
     376           0 :                                         reply[replies].resp = smb_pam_copy_fstring(
     377             :                                                 current_reply);
     378             : #ifdef DEBUG_PASSWORD
     379           0 :                                         DEBUG(100,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: We actually sent: %s\n", current_reply));
     380             : #endif
     381           0 :                                         found = True;
     382           0 :                                         break;
     383             :                                 }
     384             :                         }
     385             :                         /* PAM frees resp */
     386             : 
     387           0 :                         if (!found) {
     388           0 :                                 DEBUG(3,("smb_pam_passchange_conv: Could not find reply for PAM prompt: %s\n",msg[replies]->msg));
     389           0 :                                 free_pw_chat(pw_chat);
     390           0 :                                 SAFE_FREE(reply);
     391           0 :                                 return PAM_CONV_ERR;
     392             :                         }
     393           0 :                         break;
     394             : 
     395           0 :                 case PAM_TEXT_INFO:
     396             :                         FALL_THROUGH;
     397             : 
     398             :                 case PAM_ERROR_MSG:
     399             :                         /* ignore it... */
     400           0 :                         reply[replies].resp_retcode = PAM_SUCCESS;
     401           0 :                         reply[replies].resp = NULL;
     402           0 :                         break;
     403             : 
     404           0 :                 default:
     405             :                         /* Must be an error of some sort... */
     406           0 :                         free_pw_chat(pw_chat);
     407           0 :                         SAFE_FREE(reply);
     408           0 :                         return PAM_CONV_ERR;
     409             :                 }
     410             :         }
     411             : 
     412           0 :         free_pw_chat(pw_chat);
     413           0 :         if (reply)
     414           0 :                 *resp = reply;
     415           0 :         return PAM_SUCCESS;
     416             : }
     417             : 
     418             : /***************************************************************************
     419             :  Free up a malloced pam_conv struct.
     420             : ****************************************************************************/
     421             : 
     422           0 : static void smb_free_pam_conv(struct pam_conv *pconv)
     423             : {
     424           0 :         if (pconv)
     425           0 :                 SAFE_FREE(pconv->appdata_ptr);
     426             : 
     427           0 :         SAFE_FREE(pconv);
     428           0 : }
     429             : 
     430             : /***************************************************************************
     431             :  Allocate a pam_conv struct.
     432             : ****************************************************************************/
     433             : 
     434           0 : static struct pam_conv *smb_setup_pam_conv(smb_pam_conv_fn smb_pam_conv_fnptr, const char *user,
     435             :                                         const char *passwd, const char *newpass)
     436             : {
     437           0 :         struct pam_conv *pconv = SMB_MALLOC_P(struct pam_conv);
     438           0 :         struct smb_pam_userdata *udp = SMB_MALLOC_P(struct smb_pam_userdata);
     439             : 
     440           0 :         if (pconv == NULL || udp == NULL) {
     441           0 :                 SAFE_FREE(pconv);
     442           0 :                 SAFE_FREE(udp);
     443           0 :                 return NULL;
     444             :         }
     445             : 
     446           0 :         udp->PAM_username = user;
     447           0 :         udp->PAM_password = passwd;
     448           0 :         udp->PAM_newpassword = newpass;
     449             : 
     450           0 :         pconv->conv = smb_pam_conv_fnptr;
     451           0 :         pconv->appdata_ptr = (void *)udp;
     452           0 :         return pconv;
     453             : }
     454             : 
     455             : /* 
     456             :  * PAM Closing out cleanup handler
     457             :  */
     458             : 
     459           0 : static bool smb_pam_end(pam_handle_t *pamh, struct pam_conv *smb_pam_conv_ptr)
     460             : {
     461             :         int pam_error;
     462             : 
     463           0 :         smb_free_pam_conv(smb_pam_conv_ptr);
     464             : 
     465           0 :         if( pamh != NULL ) {
     466           0 :                 pam_error = pam_end(pamh, 0);
     467           0 :                 if(smb_pam_error_handler(pamh, pam_error, "End Cleanup Failed", 2) == True) {
     468           0 :                         DEBUG(4, ("smb_pam_end: PAM: PAM_END OK.\n"));
     469           0 :                         return True;
     470             :                 }
     471             :         }
     472           0 :         DEBUG(2,("smb_pam_end: PAM: not initialised"));
     473           0 :         return False;
     474             : }
     475             : 
     476             : /*
     477             :  * Start PAM authentication for specified account
     478             :  */
     479             : 
     480           0 : static bool smb_pam_start(pam_handle_t **pamh, const char *user, const char *rhost, struct pam_conv *pconv)
     481             : {
     482             :         int pam_error;
     483             : 
     484           0 :         *pamh = (pam_handle_t *)NULL;
     485             : 
     486           0 :         DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", user));
     487             : 
     488           0 :         pam_error = pam_start("samba", user, pconv, pamh);
     489           0 :         if( !smb_pam_error_handler(*pamh, pam_error, "Init Failed", 0)) {
     490           0 :                 *pamh = (pam_handle_t *)NULL;
     491           0 :                 return False;
     492             :         }
     493             : 
     494             : #ifdef HAVE_PAM_RHOST
     495           0 :         DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", rhost));
     496           0 :         pam_error = pam_set_item(*pamh, PAM_RHOST, rhost);
     497           0 :         if(!smb_pam_error_handler(*pamh, pam_error, "set rhost failed", 0)) {
     498           0 :                 smb_pam_end(*pamh, pconv);
     499           0 :                 *pamh = (pam_handle_t *)NULL;
     500           0 :                 return False;
     501             :         }
     502             : #endif
     503             : #ifdef HAVE_PAM_TTY
     504           0 :         DEBUG(4,("smb_pam_start: PAM: setting tty\n"));
     505           0 :         pam_error = pam_set_item(*pamh, PAM_TTY, "samba");
     506           0 :         if (!smb_pam_error_handler(*pamh, pam_error, "set tty failed", 0)) {
     507           0 :                 smb_pam_end(*pamh, pconv);
     508           0 :                 *pamh = (pam_handle_t *)NULL;
     509           0 :                 return False;
     510             :         }
     511             : #endif
     512           0 :         DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", user));
     513           0 :         return True;
     514             : }
     515             : 
     516             : /*
     517             :  * PAM Authentication Handler
     518             :  */
     519           0 : static NTSTATUS smb_pam_auth(pam_handle_t *pamh, const char *user)
     520             : {
     521             :         int pam_error;
     522           0 :         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
     523             : 
     524             :         /*
     525             :          * To enable debugging set in /etc/pam.d/samba:
     526             :          *      auth required /lib/security/pam_pwdb.so nullok shadow audit
     527             :          */
     528             : 
     529           0 :         DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user));
     530           0 :         pam_error = pam_authenticate(pamh, PAM_SILENT | (lp_null_passwords() ? 0 : PAM_DISALLOW_NULL_AUTHTOK));
     531           0 :         switch( pam_error ){
     532           0 :                 case PAM_AUTH_ERR:
     533           0 :                         DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user));
     534           0 :                         break;
     535           0 :                 case PAM_CRED_INSUFFICIENT:
     536           0 :                         DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user));
     537           0 :                         break;
     538           0 :                 case PAM_AUTHINFO_UNAVAIL:
     539           0 :                         DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user));
     540           0 :                         break;
     541           0 :                 case PAM_USER_UNKNOWN:
     542           0 :                         DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user));
     543           0 :                         break;
     544           0 :                 case PAM_MAXTRIES:
     545           0 :                         DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user));
     546           0 :                         break;
     547           0 :                 case PAM_ABORT:
     548           0 :                         DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user));
     549           0 :                         break;
     550           0 :                 case PAM_SUCCESS:
     551           0 :                         DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user));
     552           0 :                         break;
     553           0 :                 default:
     554           0 :                         DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user));
     555           0 :                         break;
     556             :         }
     557             : 
     558           0 :         smb_pam_nt_status_error_handler(pamh, pam_error, "Authentication Failure", 2, &nt_status);
     559           0 :         return nt_status;
     560             : }
     561             : 
     562             : /* 
     563             :  * PAM Account Handler
     564             :  */
     565           0 : static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user)
     566             : {
     567             :         int pam_error;
     568           0 :         NTSTATUS nt_status = NT_STATUS_ACCOUNT_DISABLED;
     569             : 
     570           0 :         DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user));
     571           0 :         pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */
     572           0 :         switch( pam_error ) {
     573           0 :                 case PAM_AUTHTOK_EXPIRED:
     574           0 :                         DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user));
     575           0 :                         break;
     576           0 :                 case PAM_ACCT_EXPIRED:
     577           0 :                         DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user));
     578           0 :                         break;
     579           0 :                 case PAM_AUTH_ERR:
     580           0 :                         DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user));
     581           0 :                         break;
     582           0 :                 case PAM_PERM_DENIED:
     583           0 :                         DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user));
     584           0 :                         break;
     585           0 :                 case PAM_USER_UNKNOWN:
     586           0 :                         DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user));
     587           0 :                         break;
     588           0 :                 case PAM_SUCCESS:
     589           0 :                         DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user));
     590           0 :                         break;
     591           0 :                 default:
     592           0 :                         DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user));
     593           0 :                         break;
     594             :         }
     595             : 
     596           0 :         smb_pam_nt_status_error_handler(pamh, pam_error, "Account Check Failed", 2, &nt_status);
     597           0 :         return nt_status;
     598             : }
     599             : 
     600             : /*
     601             :  * PAM Credential Setting
     602             :  */
     603             : 
     604           0 : static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user)
     605             : {
     606             :         int pam_error;
     607           0 :         NTSTATUS nt_status = NT_STATUS_NO_TOKEN;
     608             : 
     609             :         /*
     610             :          * This will allow samba to aquire a kerberos token. And, when
     611             :          * exporting an AFS cell, be able to /write/ to this cell.
     612             :          */
     613             : 
     614           0 :         DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user));
     615           0 :         pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT)); 
     616           0 :         switch( pam_error ) {
     617           0 :                 case PAM_CRED_UNAVAIL:
     618           0 :                         DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user ));
     619           0 :                         break;
     620           0 :                 case PAM_CRED_EXPIRED:
     621           0 :                         DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user ));
     622           0 :                         break;
     623           0 :                 case PAM_USER_UNKNOWN:
     624           0 :                         DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user ));
     625           0 :                         break;
     626           0 :                 case PAM_CRED_ERR:
     627           0 :                         DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user ));
     628           0 :                         break;
     629           0 :                 case PAM_SUCCESS:
     630           0 :                         DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user));
     631           0 :                         break;
     632           0 :                 default:
     633           0 :                         DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user));
     634           0 :                         break;
     635             :         }
     636             : 
     637           0 :         smb_pam_nt_status_error_handler(pamh, pam_error, "Set Credential Failure", 2, &nt_status);
     638           0 :         return nt_status;
     639             : }
     640             : 
     641             : /*
     642             :  * PAM Internal Session Handler
     643             :  */
     644           0 : static bool smb_internal_pam_session(pam_handle_t *pamh, const char *user, const char *tty, bool flag)
     645             : {
     646             :         int pam_error;
     647             : 
     648             : #ifdef HAVE_PAM_TTY
     649           0 :         DEBUG(4,("smb_internal_pam_session: PAM: tty set to: %s\n", tty));
     650           0 :         pam_error = pam_set_item(pamh, PAM_TTY, tty);
     651           0 :         if (!smb_pam_error_handler(pamh, pam_error, "set tty failed", 0))
     652           0 :                 return False;
     653             : #endif
     654             : 
     655           0 :         if (flag) {
     656           0 :                 pam_error = pam_open_session(pamh, PAM_SILENT);
     657           0 :                 if (!smb_pam_error_handler(pamh, pam_error, "session setup failed", 0))
     658           0 :                         return False;
     659             :         } else {
     660           0 :                 pam_setcred(pamh, (PAM_DELETE_CRED|PAM_SILENT)); /* We don't care if this fails */
     661           0 :                 pam_error = pam_close_session(pamh, PAM_SILENT); /* This will probably pick up the error anyway */
     662           0 :                 if (!smb_pam_error_handler(pamh, pam_error, "session close failed", 0))
     663           0 :                         return False;
     664             :         }
     665           0 :         return (True);
     666             : }
     667             : 
     668             : /*
     669             :  * Internal PAM Password Changer.
     670             :  */
     671             : 
     672           0 : static bool smb_pam_chauthtok(pam_handle_t *pamh, const char * user)
     673             : {
     674             :         int pam_error;
     675             : 
     676           0 :         DEBUG(4,("smb_pam_chauthtok: PAM: Password Change for User: %s\n", user));
     677             : 
     678           0 :         pam_error = pam_chauthtok(pamh, PAM_SILENT); /* Change Password */
     679             : 
     680           0 :         switch( pam_error ) {
     681           0 :         case PAM_AUTHTOK_ERR:
     682           0 :                 DEBUG(2, ("PAM: unable to obtain the new authentication token - is password to weak?\n"));
     683           0 :                 break;
     684             : 
     685             :         /* This doesn't seem to be defined on Solaris. JRA */
     686             : #ifdef PAM_AUTHTOK_RECOVER_ERR
     687           0 :         case PAM_AUTHTOK_RECOVER_ERR:
     688           0 :                 DEBUG(2, ("PAM: unable to obtain the old authentication token - was the old password wrong?.\n"));
     689           0 :                 break;
     690             : #endif
     691             : 
     692           0 :         case PAM_AUTHTOK_LOCK_BUSY:
     693           0 :                 DEBUG(2, ("PAM: unable to change the authentication token since it is currently locked.\n"));
     694           0 :                 break;
     695           0 :         case PAM_AUTHTOK_DISABLE_AGING:
     696           0 :                 DEBUG(2, ("PAM: Authentication token aging has been disabled.\n"));
     697           0 :                 break;
     698           0 :         case PAM_PERM_DENIED:
     699           0 :                 DEBUG(0, ("PAM: Permission denied.\n"));
     700           0 :                 break;
     701           0 :         case PAM_TRY_AGAIN:
     702           0 :                 DEBUG(0, ("PAM: Could not update all authentication token(s). No authentication tokens were updated.\n"));
     703           0 :                 break;
     704           0 :         case PAM_USER_UNKNOWN:
     705           0 :                 DEBUG(0, ("PAM: User not known to PAM\n"));
     706           0 :                 break;
     707           0 :         case PAM_SUCCESS:
     708           0 :                 DEBUG(4, ("PAM: Account OK for User: %s\n", user));
     709           0 :                 break;
     710           0 :         default:
     711           0 :                 DEBUG(0, ("PAM: UNKNOWN PAM ERROR (%d) for User: %s\n", pam_error, user));
     712             :         }
     713             :  
     714           0 :         if(!smb_pam_error_handler(pamh, pam_error, "Password Change Failed", 2)) {
     715           0 :                 return False;
     716             :         }
     717             : 
     718             :         /* If this point is reached, the password has changed. */
     719           0 :         return True;
     720             : }
     721             : 
     722             : /*
     723             :  * PAM Externally accessible Session handler
     724             :  */
     725             : 
     726       24530 : bool smb_pam_claim_session(const char *user, const char *tty, const char *rhost)
     727             : {
     728       24530 :         pam_handle_t *pamh = NULL;
     729       24530 :         struct pam_conv *pconv = NULL;
     730             : 
     731             :         /* Ignore PAM if told to. */
     732             : 
     733       24530 :         if (!lp_obey_pam_restrictions())
     734       24010 :                 return True;
     735             : 
     736           0 :         if ((pconv = smb_setup_pam_conv(smb_pam_conv, user, NULL, NULL)) == NULL)
     737           0 :                 return False;
     738             : 
     739           0 :         if (!smb_pam_start(&pamh, user, rhost, pconv))
     740           0 :                 return False;
     741             : 
     742           0 :         if (!smb_internal_pam_session(pamh, user, tty, True)) {
     743           0 :                 smb_pam_end(pamh, pconv);
     744           0 :                 return False;
     745             :         }
     746             : 
     747           0 :         return smb_pam_end(pamh, pconv);
     748             : }
     749             : 
     750             : /*
     751             :  * PAM Externally accessible Session handler
     752             :  */
     753             : 
     754       25276 : bool smb_pam_close_session(const char *user, const char *tty, const char *rhost)
     755             : {
     756       25276 :         pam_handle_t *pamh = NULL;
     757       25276 :         struct pam_conv *pconv = NULL;
     758             : 
     759             :         /* Ignore PAM if told to. */
     760             : 
     761       25276 :         if (!lp_obey_pam_restrictions())
     762       24754 :                 return True;
     763             : 
     764           0 :         if ((pconv = smb_setup_pam_conv(smb_pam_conv, user, NULL, NULL)) == NULL)
     765           0 :                 return False;
     766             : 
     767           0 :         if (!smb_pam_start(&pamh, user, rhost, pconv))
     768           0 :                 return False;
     769             : 
     770           0 :         if (!smb_internal_pam_session(pamh, user, tty, False)) {
     771           0 :                 smb_pam_end(pamh, pconv);
     772           0 :                 return False;
     773             :         }
     774             : 
     775           0 :         return smb_pam_end(pamh, pconv);
     776             : }
     777             : 
     778             : /*
     779             :  * PAM Externally accessible Account handler
     780             :  */
     781             : 
     782       18215 : NTSTATUS smb_pam_accountcheck(const char *user, const char *rhost)
     783             : {
     784       18215 :         NTSTATUS nt_status = NT_STATUS_ACCOUNT_DISABLED;
     785       18215 :         pam_handle_t *pamh = NULL;
     786       18215 :         struct pam_conv *pconv = NULL;
     787             : 
     788             :         /* Ignore PAM if told to. */
     789             : 
     790       18215 :         if (!lp_obey_pam_restrictions())
     791       18215 :                 return NT_STATUS_OK;
     792             : 
     793           0 :         if ((pconv = smb_setup_pam_conv(smb_pam_conv, user, NULL, NULL)) == NULL)
     794           0 :                 return NT_STATUS_NO_MEMORY;
     795             : 
     796           0 :         if (!smb_pam_start(&pamh, user, rhost, pconv))
     797           0 :                 return NT_STATUS_ACCOUNT_DISABLED;
     798             : 
     799           0 :         if (!NT_STATUS_IS_OK(nt_status = smb_pam_account(pamh, user)))
     800           0 :                 DEBUG(0, ("smb_pam_accountcheck: PAM: Account Validation Failed - Rejecting User %s!\n", user));
     801             : 
     802           0 :         smb_pam_end(pamh, pconv);
     803           0 :         return nt_status;
     804             : }
     805             : 
     806             : /*
     807             :  * PAM Password Validation Suite
     808             :  */
     809             : 
     810           0 : NTSTATUS smb_pam_passcheck(const char * user, const char * rhost,
     811             :                            const char * password)
     812             : {
     813           0 :         pam_handle_t *pamh = NULL;
     814           0 :         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
     815           0 :         struct pam_conv *pconv = NULL;
     816             : 
     817             :         /*
     818             :          * Note we can't ignore PAM here as this is the only
     819             :          * way of doing auths on plaintext passwords when
     820             :          * compiled --with-pam.
     821             :          */
     822             : 
     823           0 :         if ((pconv = smb_setup_pam_conv(smb_pam_conv, user, password, NULL)) == NULL)
     824           0 :                 return NT_STATUS_LOGON_FAILURE;
     825             : 
     826           0 :         if (!smb_pam_start(&pamh, user, rhost, pconv))
     827           0 :                 return NT_STATUS_LOGON_FAILURE;
     828             : 
     829           0 :         if (!NT_STATUS_IS_OK(nt_status = smb_pam_auth(pamh, user))) {
     830           0 :                 DEBUG(0, ("smb_pam_passcheck: PAM: smb_pam_auth failed - Rejecting User %s !\n", user));
     831           0 :                 smb_pam_end(pamh, pconv);
     832           0 :                 return nt_status;
     833             :         }
     834             : 
     835           0 :         if (!NT_STATUS_IS_OK(nt_status = smb_pam_account(pamh, user))) {
     836           0 :                 DEBUG(0, ("smb_pam_passcheck: PAM: smb_pam_account failed - Rejecting User %s !\n", user));
     837           0 :                 smb_pam_end(pamh, pconv);
     838           0 :                 return nt_status;
     839             :         }
     840             : 
     841           0 :         if (!NT_STATUS_IS_OK(nt_status = smb_pam_setcred(pamh, user))) {
     842           0 :                 DEBUG(0, ("smb_pam_passcheck: PAM: smb_pam_setcred failed - Rejecting User %s !\n", user));
     843           0 :                 smb_pam_end(pamh, pconv);
     844           0 :                 return nt_status;
     845             :         }
     846             : 
     847           0 :         smb_pam_end(pamh, pconv);
     848           0 :         return nt_status;
     849             : }
     850             : 
     851             : /*
     852             :  * PAM Password Change Suite
     853             :  */
     854             : 
     855           0 : bool smb_pam_passchange(const char *user, const char *rhost,
     856             :                         const char *oldpassword, const char *newpassword)
     857             : {
     858             :         /* Appropriate quantities of root should be obtained BEFORE calling this function */
     859           0 :         struct pam_conv *pconv = NULL;
     860           0 :         pam_handle_t *pamh = NULL;
     861             : 
     862           0 :         if ((pconv = smb_setup_pam_conv(smb_pam_passchange_conv, user, oldpassword, newpassword)) == NULL)
     863           0 :                 return False;
     864             : 
     865           0 :         if(!smb_pam_start(&pamh, user, rhost, pconv))
     866           0 :                 return False;
     867             : 
     868           0 :         if (!smb_pam_chauthtok(pamh, user)) {
     869           0 :                 DEBUG(0, ("smb_pam_passchange: PAM: Password Change Failed for user %s!\n", user));
     870           0 :                 smb_pam_end(pamh, pconv);
     871           0 :                 return False;
     872             :         }
     873             : 
     874           0 :         return smb_pam_end(pamh, pconv);
     875             : }
     876             : 
     877             : #else
     878             : 
     879             : /* If PAM not used, no PAM restrictions on accounts. */
     880             : NTSTATUS smb_pam_accountcheck(const char *user, const char *rhost)
     881             : {
     882             :         return NT_STATUS_OK;
     883             : }
     884             : 
     885             : /* If PAM not used, also no PAM restrictions on sessions. */
     886             : bool smb_pam_claim_session(const char *user, const char *tty, const char *rhost)
     887             : {
     888             :         return True;
     889             : }
     890             : 
     891             : /* If PAM not used, also no PAM restrictions on sessions. */
     892             : bool smb_pam_close_session(const char *in_user, const char *tty, const char *rhost)
     893             : {
     894             :         return True;
     895             : }
     896             : #endif /* WITH_PAM */

Generated by: LCOV version 1.13