📄 support.c
字号:
/* Unix NT password database implementation, version 0.6. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 675 * Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" #include "general.h" #include "support.h" #define _pam_overwrite(x) \ do { \ register char *__xx__; \ if ((__xx__=(x))) \ while (*__xx__) \ *__xx__++ = '\0'; \ } while (0) /* * Don't just free it, forget it too. */ #define _pam_drop(X) \ do { \ if (X) { \ free(X); \ X=NULL; \ } \ } while (0) #define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ do { \ int reply_i; \ \ for (reply_i=0; reply_i<replies; ++reply_i) { \ if (reply[reply_i].resp) { \ _pam_overwrite(reply[reply_i].resp); \ free(reply[reply_i].resp); \ } \ } \ if (reply) \ free(reply); \ } while (0) int converse(pam_handle_t *, int, int, struct pam_message **, struct pam_response **); int make_remark(pam_handle_t *, unsigned int, int, const char *); void _cleanup(pam_handle_t *, void *, int); char *_pam_delete(register char *); /* default configuration file location */ char *servicesf = dyn_CONFIGFILE; /* syslogging function for errors and other information */ void _log_err( int err, const char *format, ... ) { va_list args; va_start( args, format ); openlog( "PAM_smbpass", LOG_CONS | LOG_PID, LOG_AUTH ); vsyslog( err, format, args ); va_end( args ); closelog(); } /* this is a front-end for module-application conversations */ int converse( pam_handle_t * pamh, int ctrl, int nargs , struct pam_message **message , struct pam_response **response ) { int retval; struct pam_conv *conv; retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv); if (retval == PAM_SUCCESS) { retval = conv->conv(nargs, (const struct pam_message **) message ,response, conv->appdata_ptr); if (retval != PAM_SUCCESS && on(SMB_DEBUG, ctrl)) { _log_err(LOG_DEBUG, "conversation failure [%s]" ,pam_strerror(pamh, retval)); } } else { _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" ,pam_strerror(pamh, retval)); } return retval; /* propagate error status */ } int make_remark( pam_handle_t * pamh, unsigned int ctrl , int type, const char *text ) { if (off(SMB__QUIET, ctrl)) { struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; pmsg[0] = &msg[0]; msg[0].msg = text; msg[0].msg_style = type; resp = NULL; return converse(pamh, ctrl, 1, pmsg, &resp); } return PAM_SUCCESS; } /* set the control flags for the SMB module. */int set_ctrl( int flags, int argc, const char **argv ){ int i = 0; const char *service_file = dyn_CONFIGFILE; unsigned int ctrl; ctrl = SMB_DEFAULTS; /* the default selection of options */ /* set some flags manually */ /* A good, sane default (matches Samba's behavior). */ set( SMB__NONULL, ctrl ); /* initialize service file location */ service_file=servicesf; if (flags & PAM_SILENT) { set( SMB__QUIET, ctrl ); } /* Run through the arguments once, looking for an alternate smb config file location */ while (i < argc) { int j; for (j = 0; j < SMB_CTRLS_; ++j) { if (smb_args[j].token && !strncmp(argv[i], smb_args[j].token, strlen(smb_args[j].token))) { break; } } if (j == SMB_CONF_FILE) { service_file = argv[i] + 8; } i++; } /* Read some options from the Samba config. Can be overridden by the PAM config. */ if(lp_load(service_file,True,False,False) == False) { _log_err( LOG_ERR, "Error loading service file %s", service_file ); } secrets_init(); if (lp_null_passwords()) { set( SMB__NULLOK, ctrl ); } /* now parse the rest of the arguments to this module */ while (argc-- > 0) { int j; for (j = 0; j < SMB_CTRLS_; ++j) { if (smb_args[j].token && !strncmp(*argv, smb_args[j].token, strlen(smb_args[j].token))) { break; } } if (j >= SMB_CTRLS_) { _log_err( LOG_ERR, "unrecognized option [%s]", *argv ); } else { ctrl &= smb_args[j].mask; /* for turning things off */ ctrl |= smb_args[j].flag; /* for turning things on */ } ++argv; /* step to next argument */ } /* auditing is a more sensitive version of debug */ if (on( SMB_AUDIT, ctrl )) { set( SMB_DEBUG, ctrl ); } /* return the set of flags */ return ctrl;}/* use this to free strings. ESPECIALLY password strings */char * _pam_delete( register char *xx ){ _pam_overwrite( xx ); _pam_drop( xx ); return NULL;}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 *newstr = NULL; if (x != NULL) { register int i; for (i = 0; x[i]; ++i); /* length of string */ if ((newstr = SMB_MALLOC_ARRAY(char, ++i)) == NULL) { i = 0; _log_err( LOG_CRIT, "out of memory in smbpXstrDup" ); } else { while (i-- > 0) { newstr[i] = x[i]; } } x = NULL; } return newstr; /* return the duplicate or NULL on error */}/* ************************************************************** * * Useful non-trivial functions * * ************************************************************** */void _cleanup_failures( pam_handle_t * pamh, void *fl, int err ){ int quiet; const char *service = NULL; struct _pam_failed_auth *failure;#ifdef PAM_DATA_SILENT quiet = err & PAM_DATA_SILENT; /* should we log something? */#else quiet = 0;#endif#ifdef PAM_DATA_REPLACE err &= PAM_DATA_REPLACE; /* are we just replacing data? */#endif failure = (struct _pam_failed_auth *) fl; if (failure != NULL) {#ifdef PAM_DATA_SILENT if (!quiet && !err) { /* under advisement from Sun,may go away */#else if (!quiet) { /* under advisement from Sun,may go away */#endif /* log the number of authentication failures */ if (failure->count != 0) { pam_get_item( pamh, PAM_SERVICE, (const void **) &service ); _log_err( LOG_NOTICE , "%d authentication %s " "from %s for service %s as %s(%d)" , failure->count , failure->count == 1 ? "failure" : "failures" , failure->agent , service == NULL ? "**unknown**" : service , failure->user, failure->id ); if (failure->count > SMB_MAX_RETRIES) { _log_err( LOG_ALERT , "service(%s) ignoring max retries; %d > %d" , service == NULL ? "**unknown**" : service , failure->count , SMB_MAX_RETRIES ); } } } _pam_delete( failure->agent ); /* tidy up */ _pam_delete( failure->user ); /* tidy up */ SAFE_FREE( failure ); }}int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass, const char *p, unsigned int ctrl ){ uchar lm_pw[16]; uchar nt_pw[16]; int retval = PAM_AUTH_ERR; char *data_name; const char *name; if (!sampass) return PAM_ABORT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -