diff options
author | Simo Sorce <idra@samba.org> | 2002-01-12 23:12:13 +0000 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2002-01-12 23:12:13 +0000 |
commit | b79fa88b4db3bc88b0a5ae567b19286f64fd113c (patch) | |
tree | b39c595a8651552f34335a2443d31d27a20379e3 | |
parent | c9d350a736ca71f838cf19386b04e972200ee595 (diff) | |
download | samba-b79fa88b4db3bc88b0a5ae567b19286f64fd113c.tar.gz samba-b79fa88b4db3bc88b0a5ae567b19286f64fd113c.tar.bz2 samba-b79fa88b4db3bc88b0a5ae567b19286f64fd113c.zip |
updates from 2.2
(This used to be commit 398b4ff0d40d89b3e96d481807f85f15b7a7966a)
-rw-r--r-- | source3/pam_smbpass/README | 4 | ||||
-rw-r--r-- | source3/pam_smbpass/pam_smb_acct.c | 11 | ||||
-rw-r--r-- | source3/pam_smbpass/pam_smb_auth.c | 57 | ||||
-rw-r--r-- | source3/pam_smbpass/pam_smb_passwd.c | 58 | ||||
-rw-r--r-- | source3/pam_smbpass/support.c | 94 | ||||
-rw-r--r-- | source3/pam_smbpass/support.h | 12 |
6 files changed, 141 insertions, 95 deletions
diff --git a/source3/pam_smbpass/README b/source3/pam_smbpass/README index 2a9641c5d7..cf208a9914 100644 --- a/source3/pam_smbpass/README +++ b/source3/pam_smbpass/README @@ -59,8 +59,8 @@ and for the occasional good-natured complaint about the project's status that keep me working on it :) * and of course, all the other members of the Samba team -<samba@samba.org>, for creating a great product and for giving this -project a purpose +<http://www.samba.org/samba/team.html>, for creating a great product +and for giving this project a purpose --------------------- Stephen Langasek <vorlon@netexpress.net> diff --git a/source3/pam_smbpass/pam_smb_acct.c b/source3/pam_smbpass/pam_smb_acct.c index 8ed3ad7eda..8d91c456bf 100644 --- a/source3/pam_smbpass/pam_smb_acct.c +++ b/source3/pam_smbpass/pam_smb_acct.c @@ -46,12 +46,14 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, const char *name; const char *p; - struct smb_passwd *smb_pwent = NULL; + SAM_ACCOUNT *sampass = NULL; extern BOOL in_client; /* Samba initialization. */ setup_logging( "pam_smbpass", False ); + charset_initialise(); + codepage_initialise(lp_client_code_page()); in_client = True; ctrl = set_ctrl( flags, argc, argv ); @@ -75,12 +77,13 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, } /* Get the user's record. */ - smb_pwent = getsmbpwnam( name ); + pdb_init_sam(&sampass); + pdb_getsampwnam(sampass, name ); - if (!smb_pwent) + if (!sampass) return PAM_USER_UNKNOWN; - if (smb_pwent->acct_ctrl & ACB_DISABLED) { + if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { if (on( SMB_DEBUG, ctrl )) { _log_err( LOG_DEBUG , "acct: account %s is administratively disabled", name ); diff --git a/source3/pam_smbpass/pam_smb_auth.c b/source3/pam_smbpass/pam_smb_auth.c index 4b56b2b301..9952eb94db 100644 --- a/source3/pam_smbpass/pam_smb_auth.c +++ b/source3/pam_smbpass/pam_smb_auth.c @@ -45,7 +45,7 @@ do { \ } while (0) static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, - const char *name, struct smb_passwd *smb_pwent); + const char *name, SAM_ACCOUNT *sampass, BOOL exist); /* * pam_sm_authenticate() authenticates users against the samba password file. @@ -61,24 +61,25 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, { unsigned int ctrl; int retval, *ret_data = NULL; - + SAM_ACCOUNT *sampass = NULL; + extern BOOL in_client; const char *name; + BOOL found; /* Points to memory managed by the PAM library. Do not free. */ const char *p = NULL; - struct smb_passwd *smb_pwent = NULL; - - extern BOOL in_client; /* Samba initialization. */ setup_logging("pam_smbpass",False); + charset_initialise(); + codepage_initialise(lp_client_code_page()); in_client = True; ctrl = set_ctrl(flags, argc, argv); /* Get a few bytes so we can pass our return value to - pam_sm_setcred(). Used in AUTH_RETURN macro */ + pam_sm_setcred(). */ ret_data = malloc(sizeof(int)); /* get the username */ @@ -99,42 +100,46 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, AUTH_RETURN; } - smb_pwent = getsmbpwnam( name ); + pdb_init_sam(&sampass); + + found = pdb_getsampwnam( sampass, name ); if (on( SMB_MIGRATE, ctrl )) { - retval = _smb_add_user(pamh, ctrl, name, smb_pwent); + retval = _smb_add_user(pamh, ctrl, name, sampass, found); + pdb_free_sam(&sampass); AUTH_RETURN; } - if (smb_pwent == NULL) { + if (!found) { _log_err(LOG_ALERT, "Failed to find entry for user %s.", name); retval = PAM_USER_UNKNOWN; + pdb_free_sam(&sampass); + sampass = NULL; AUTH_RETURN; } /* if this user does not have a password... */ - if (_smb_blankpasswd( ctrl, smb_pwent )) { - smb_pwent = NULL; + if (_smb_blankpasswd( ctrl, sampass )) { + pdb_free_sam(&sampass); retval = PAM_SUCCESS; AUTH_RETURN; } /* get this user's authentication token */ - retval = _smb_read_password(pamh, ctrl, NULL, "Password: ", NULL - , _SMB_AUTHTOK, &p); + retval = _smb_read_password(pamh, ctrl, NULL, "Password: ", NULL, _SMB_AUTHTOK, &p); if (retval != PAM_SUCCESS ) { _log_err(LOG_CRIT, "auth: no password provided for [%s]" , name); - smb_pwent = NULL; + pdb_free_sam(&sampass); AUTH_RETURN; } /* verify the password of this user */ - retval = _smb_verify_password( pamh, smb_pwent, p, ctrl ); - smb_pwent = NULL; + retval = _smb_verify_password( pamh, sampass, p, ctrl ); + pdb_free_sam(&sampass); p = NULL; AUTH_RETURN; } @@ -154,7 +159,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, pam_get_data(pamh, "smb_setcred_return", (const void **) &pretval); if(pretval) { retval = *pretval; - free(pretval); + SAFE_FREE(pretval); } pam_set_data(pamh, "smb_setcred_return", NULL, NULL); @@ -164,7 +169,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, /* Helper function for adding a user to the db. */ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, - const char *name, struct smb_passwd *smb_pwent) + const char *name, SAM_ACCOUNT *sampass, BOOL exist) { pstring err_str; pstring msg_str; @@ -186,8 +191,8 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, } /* Add the user to the db if they aren't already there. */ - if (smb_pwent == NULL) { - retval = local_password_change( name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD, + if (!exist) { + retval = local_password_change( name, LOCAL_ADD_USER, pass, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); @@ -204,14 +209,12 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, pass = NULL; return PAM_IGNORE; - } - + } + else { /* Change the user's password IFF it's null. */ - if (smb_pwent->smb_passwd == NULL && (smb_pwent->acct_ctrl & ACB_PWNOTREQ)) + if ((pdb_get_lanman_passwd(sampass) == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) { - retval = local_password_change( name, LOCAL_SET_PASSWORD, - pass, err_str, - sizeof(err_str), + retval = local_password_change( name, 0, pass, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); if (!retval && *err_str) { @@ -224,6 +227,8 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str ); } } + } + pass = NULL; return PAM_IGNORE; diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c index 8c207cee0d..338d873d25 100644 --- a/source3/pam_smbpass/pam_smb_passwd.c +++ b/source3/pam_smbpass/pam_smb_passwd.c @@ -33,8 +33,7 @@ #include "support.h" -int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user - , const char *pass_new ) +int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *pass_new ) { char c; int retval, i; @@ -44,7 +43,7 @@ int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user err_str[0] = '\0'; msg_str[0] = '\0'; - retval = local_password_change( user, LOCAL_SET_PASSWORD, pass_new, err_str, sizeof(err_str), + retval = local_password_change( user, 0, pass_new, err_str, sizeof(err_str), msg_str, sizeof(msg_str) ); if (!retval) { @@ -93,12 +92,14 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, extern BOOL in_client; - struct smb_passwd *smb_pwent=NULL; + SAM_ACCOUNT *sampass = NULL; const char *user; const char *pass_old, *pass_new; /* Samba initialization. */ setup_logging( "pam_smbpass", False ); + charset_initialise(); + codepage_initialise(lp_client_code_page()); in_client = True; ctrl = set_ctrl(flags, argc, argv); @@ -125,9 +126,10 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } /* obtain user record */ - smb_pwent = getsmbpwnam(user); + pdb_init_sam(&sampass); + pdb_getsampwnam(sampass,user); - if (smb_pwent == NULL) { + if (sampass == NULL) { _log_err( LOG_ALERT, "Failed to find entry for user %s.", user ); return PAM_USER_UNKNOWN; } @@ -140,10 +142,10 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, char *Announce; - if (_smb_blankpasswd( ctrl, smb_pwent )) { + if (_smb_blankpasswd( ctrl, sampass )) { + pdb_free_sam(&sampass); return PAM_SUCCESS; - } /* Password change by root, or for an expired token, doesn't @@ -155,6 +157,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, Announce = (char *) malloc(sizeof(greeting)+strlen(user)); if (Announce == NULL) { _log_err(LOG_CRIT, "password: out of memory"); + pdb_free_sam(&sampass); return PAM_BUF_ERR; } strncpy( Announce, greeting, sizeof(greeting) ); @@ -162,23 +165,20 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, #undef greeting set( SMB__OLD_PASSWD, ctrl ); - retval = _smb_read_password( pamh, ctrl - , Announce - , "Current SMB password: " - , NULL - , _SMB_OLD_AUTHTOK - , &pass_old ); - free( Announce ); + retval = _smb_read_password( pamh, ctrl, Announce, "Current SMB password: ", + NULL, _SMB_OLD_AUTHTOK, &pass_old ); + SAFE_FREE( Announce ); if (retval != PAM_SUCCESS) { _log_err( LOG_NOTICE , "password - (old) token not obtained" ); + pdb_free_sam(&sampass); return retval; } /* verify that this is the password for this user */ - retval = _smb_verify_password( pamh, smb_pwent, pass_old, ctrl ); + retval = _smb_verify_password( pamh, sampass, pass_old, ctrl ); } else { pass_old = NULL; @@ -186,16 +186,20 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } pass_old = NULL; + pdb_free_sam(&sampass); return retval; } else if (flags & PAM_UPDATE_AUTHTOK) { +#if 0 + /* We used to return when this flag was set, but that breaks + password synchronization when /other/ tokens are expired. For + now, we change the password whenever we're asked. SRL */ if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) { - /* NOTE: there is currently no support for password expiring - under Samba. Support will be added here when it becomes - available. */ + pdb_free_sam(&sampass); return PAM_SUCCESS; } +#endif /* * obtain the proposed password */ @@ -220,6 +224,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (retval != PAM_SUCCESS) { _log_err( LOG_NOTICE, "password: user not authenticated" ); + pdb_free_sam(&sampass); return retval; } @@ -246,6 +251,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, , "password: new password not obtained" ); } pass_old = NULL; /* tidy up */ + pdb_free_sam(&sampass); return retval; } @@ -264,6 +270,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (retval != PAM_SUCCESS) { _log_err(LOG_NOTICE, "new password not acceptable"); pass_new = pass_old = NULL; /* tidy up */ + pdb_free_sam(&sampass); return retval; } @@ -278,7 +285,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (retval == PAM_SUCCESS) { /* password updated */ _log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)" - , user, smb_pwent->smb_userid, uidtoname( getuid() ) + , user, pdb_get_uid(sampass), uidtoname( getuid() ) , getuid() ); } else { _log_err( LOG_ERR, "password change failed for user %s" @@ -286,7 +293,10 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } pass_old = pass_new = NULL; - smb_pwent = NULL; + if (sampass) { + pdb_free_sam(&sampass); + sampass = NULL; + } } else { /* something has broken with the library */ @@ -294,7 +304,13 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = PAM_ABORT; } + + if (sampass) { + pdb_free_sam(&sampass); + sampass = NULL; + } + pdb_free_sam(&sampass); return retval; } diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c index f35a354b7c..86349f8c16 100644 --- a/source3/pam_smbpass/support.c +++ b/source3/pam_smbpass/support.c @@ -125,7 +125,8 @@ int make_remark( pam_handle_t * pamh, unsigned int ctrl int set_ctrl( int flags, int argc, const char **argv ) { int i = 0; - const char *service_file = dyn_CONFIGFILE; + static pstring servicesf = CONFIGFILE; + const char *service_file = servicesf; unsigned int ctrl; ctrl = SMB_DEFAULTS; /* the default selection of options */ @@ -215,6 +216,33 @@ void _cleanup( pam_handle_t * pamh, void *x, int error_status ) x = _pam_delete( (char *) x ); } +/* JHT + * + * Safe duplication of character strings. "Paranoid"; don't leave + * evidence of old token around for later stack analysis. + * + */ +char * smbpXstrDup( const char *x ) +{ + register char *new = NULL; + + if (x != NULL) { + register int i; + + for (i = 0; x[i]; ++i); /* length of string */ + if ((new = malloc(++i)) == NULL) { + i = 0; + _log_err( LOG_CRIT, "out of memory in smbpXstrDup" ); + } else { + while (i-- > 0) { + new[i] = x[i]; + } + } + x = NULL; + } + return new; /* return the duplicate or NULL on error */ +} + /* ************************************************************** * * Useful non-trivial functions * * ************************************************************** */ @@ -265,13 +293,12 @@ void _cleanup_failures( pam_handle_t * pamh, void *fl, int err ) } _pam_delete( failure->agent ); /* tidy up */ _pam_delete( failure->user ); /* tidy up */ - free( failure ); + SAFE_FREE( failure ); } } -int _smb_verify_password( pam_handle_t * pamh - , const struct smb_passwd *smb_pwent - , const char *p, unsigned int ctrl ) +int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass, + const char *p, unsigned int ctrl ) { uchar hash_pass[16]; uchar lm_pw[16]; @@ -280,10 +307,10 @@ int _smb_verify_password( pam_handle_t * pamh char *data_name; const char *name; - if (!smb_pwent) + if (!sampass) return PAM_ABORT; - name = smb_pwent->smb_name; + name = pdb_get_username(sampass); #ifdef HAVE_PAM_FAIL_DELAY if (off( SMB_NODELAY, ctrl )) { @@ -291,13 +318,13 @@ int _smb_verify_password( pam_handle_t * pamh } #endif - if (!smb_pwent->smb_passwd) + if (!pdb_get_lanman_passwd(sampass)) { _log_err( LOG_DEBUG, "user %s has null SMB password" , name ); if (off( SMB__NONULL, ctrl ) - && (smb_pwent->acct_ctrl & ACB_PWNOTREQ)) + && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) { /* this means we've succeeded */ return PAM_SUCCESS; } else { @@ -308,13 +335,12 @@ int _smb_verify_password( pam_handle_t * pamh , "failed auth request by %s for service %s as %s(%d)" , uidtoname( getuid() ) , service ? service : "**unknown**", name - , smb_pwent->smb_userid ); + , pdb_get_uid(sampass) ); return PAM_AUTH_ERR; } } - data_name = (char *) malloc( sizeof(FAIL_PREFIX) - + strlen( name )); + data_name = (char *) malloc( sizeof(FAIL_PREFIX) + strlen( name )); if (data_name == NULL) { _log_err( LOG_CRIT, "no memory for data-name" ); } @@ -326,9 +352,9 @@ int _smb_verify_password( pam_handle_t * pamh if (strlen( p ) == 16 || (strlen( p ) == 32 && pdb_gethexpwd( p, (char *) hash_pass ))) { - if (!memcmp( hash_pass, smb_pwent->smb_passwd, 16 ) - || (smb_pwent->smb_nt_passwd - && !memcmp( hash_pass, smb_pwent->smb_nt_passwd, 16 ))) + if (!memcmp( hash_pass, pdb_get_lanman_passwd(sampass), 16 ) + || (pdb_get_nt_passwd(sampass) + && !memcmp( hash_pass, pdb_get_nt_passwd(sampass), 16 ))) { retval = PAM_SUCCESS; if (data_name) { /* reset failures */ @@ -336,7 +362,6 @@ int _smb_verify_password( pam_handle_t * pamh } _pam_delete( data_name ); memset( hash_pass, '\0', 16 ); - smb_pwent = NULL; return retval; } } @@ -351,7 +376,7 @@ int _smb_verify_password( pam_handle_t * pamh /* the moment of truth -- do we agree with the password? */ - if (!memcmp( nt_pw, smb_pwent->smb_nt_passwd, 16 )) { + if (!memcmp( nt_pw, pdb_get_nt_passwd(sampass), 16 )) { retval = PAM_SUCCESS; if (data_name) { /* reset failures */ @@ -387,12 +412,12 @@ int _smb_verify_password( pam_handle_t * pamh , "failed auth request by %s for service %s as %s(%d)" , uidtoname( getuid() ) , service ? service : "**unknown**", name - , smb_pwent->smb_userid ); + , pdb_get_uid(sampass) ); new->count = 1; } - new->user = smb_xstrdup( name ); - new->id = smb_pwent->smb_userid; - new->agent = smb_xstrdup( uidtoname( getuid() ) ); + new->user = smbpXstrDup( name ); + new->id = pdb_get_uid(sampass); + new->agent = smbpXstrDup( uidtoname( getuid() ) ); pam_set_data( pamh, data_name, new, _cleanup_failures ); } else { @@ -401,20 +426,20 @@ int _smb_verify_password( pam_handle_t * pamh , "failed auth request by %s for service %s as %s(%d)" , uidtoname( getuid() ) , service ? service : "**unknown**", name - , smb_pwent->smb_userid ); + , pdb_get_uid(sampass) ); } } else { _log_err( LOG_NOTICE , "failed auth request by %s for service %s as %s(%d)" , uidtoname( getuid() ) , service ? service : "**unknown**", name - , smb_pwent->smb_userid ); + , pdb_get_uid(sampass) ); retval = PAM_AUTH_ERR; } } _pam_delete( data_name ); - smb_pwent = NULL; + return retval; } @@ -426,7 +451,7 @@ int _smb_verify_password( pam_handle_t * pamh * - to avoid prompting for one in such cases (CG) */ -int _smb_blankpasswd( unsigned int ctrl, const struct smb_passwd *smb_pwent ) +int _smb_blankpasswd( unsigned int ctrl, SAM_ACCOUNT *sampass ) { int retval; @@ -439,7 +464,7 @@ int _smb_blankpasswd( unsigned int ctrl, const struct smb_passwd *smb_pwent ) if (on( SMB__NONULL, ctrl )) return 0; /* will fail but don't let on yet */ - if (smb_pwent->smb_passwd == NULL) + if (pdb_get_lanman_passwd(sampass) == NULL) retval = 1; else retval = 0; @@ -451,10 +476,9 @@ int _smb_blankpasswd( unsigned int ctrl, const struct smb_passwd *smb_pwent ) * obtain a password from the user */ -int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl - , const char *comment, const char *prompt1 - , const char *prompt2, const char *data_name - , const char **pass ) +int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, + const char *comment, const char *prompt1, + const char *prompt2, const char *data_name, char **pass ) { int authtok_flag; int retval; @@ -533,7 +557,7 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl if (retval == PAM_SUCCESS) { /* a good conversation */ - token = smb_xstrdup(resp[j++].resp); + token = smbpXstrDup(resp[j++].resp); if (token != NULL) { if (expect == 2) { /* verify that password entered correctly */ @@ -602,10 +626,10 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl return PAM_SUCCESS; } -int _pam_smb_approve_pass(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *pass_old - ,const char *pass_new) +int _pam_smb_approve_pass(pam_handle_t * pamh, + unsigned int ctrl, + const char *pass_old, + const char *pass_new ) { /* Further checks should be handled through module stacking. -SRL */ diff --git a/source3/pam_smbpass/support.h b/source3/pam_smbpass/support.h index 85bbd0a523..a13a2d0aeb 100644 --- a/source3/pam_smbpass/support.h +++ b/source3/pam_smbpass/support.h @@ -12,7 +12,7 @@ extern void _cleanup(pam_handle_t *, void *, int); * evidence of old token around for later stack analysis. */ -extern char *xstrdup(const char *); +extern char *smbpXstrDup(const char *); /* ************************************************************** * * Useful non-trivial functions * @@ -26,9 +26,8 @@ extern BOOL strequal(const char *, const char *); extern struct smb_passwd * _my_get_smbpwnam(FILE *, const char *, BOOL *, BOOL *, long *); -extern int _smb_verify_password( pam_handle_t *pamh - , const struct smb_passwd *smb_pwent - , const char *p, unsigned int ctrl ); +extern int _smb_verify_password( pam_handle_t *pamh , SAM_ACCOUNT *sampass, + const char *p, unsigned int ctrl ); /* * this function obtains the name of the current user and ensures @@ -40,13 +39,12 @@ extern int _smb_get_user(pam_handle_t *, unsigned int, /* _smb_blankpasswd() is a quick check for a blank password */ -extern int _smb_blankpasswd(unsigned int, const struct smb_passwd *); +extern int _smb_blankpasswd(unsigned int, SAM_ACCOUNT *); /* obtain a password from the user */ extern int _smb_read_password( pam_handle_t *, unsigned int, const char*, - const char *, const char *, const char *, - const char **); + const char *, const char *, const char *, char **); extern int _pam_smb_approve_pass(pam_handle_t *, unsigned int, const char *, const char *); |