📄 vchkpw.c
字号:
if ( l==i ) break; } /* open the log if configured */ if ( ENABLE_LOGGING > 0 ) { openlog(LOG_NAME,LOG_PID,LOG_MAIL); } if ( TheName[0] == 0 ) { snprintf(LogLine, sizeof(LogLine), "%s: null user name given %s:%s", VchkpwLogName, TheName, IpAddr); vlog(VLOG_ERROR_LOGON, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(12); } if ( ThePass[0] == 0 ) { snprintf(LogLine, sizeof(LogLine), "%s: null password given %s:%s", VchkpwLogName, TheName, IpAddr); vlog(VLOG_ERROR_PASSWD, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(13); }}void login_virtual_user(){ int apopaccepted = -1; int cramaccepted = -1; char AuthType[15] = "PLAIN"; /* If thier directory path is empty make them a new one */ if ( vpw->pw_dir == NULL || vpw->pw_dir[0]==0 ) { /* if making a new directory failed log the error and exit */ if ( make_user_dir(vpw->pw_name, TheDomain, pw_uid, pw_gid)==NULL){ snprintf(LogLine, sizeof(LogLine), "%s: dir auto create failed %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(14); } /* Re-read the vpw entry, because we need to lookup the newly created * pw_dir entry */ if ((vpw=vauth_getpw(TheUser, TheDomain)) == NULL ) { snprintf(LogLine, sizeof(LogLine), "%s: failed to vauth_getpw() after dir auto create %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(14); } }#ifdef CLEAR_PASS /* Check CRAM-MD5 auth */ if(ConnType == SMTP_CONN) { /* printf("vchkpw: smtp auth\n"); */ cramaccepted = authcram(ThePass,TheChallenge,vpw->pw_clear_passwd); if(cramaccepted == 0) strcpy(AuthType, "CRAM-MD5"); } /* Check APOP auth */ if(ConnType == POP_CONN) { apopaccepted = authapop(ThePass,TheChallenge,vpw->pw_clear_passwd); if(apopaccepted == 0) strcpy(AuthType, "APOP"); }#endif#ifdef ENABLE_LEARN_PASSWORDS /* check for a valid vpopmail passwd field */ if ( vpw->pw_passwd==NULL||vpw->pw_passwd[0]==0) { mkpasswd3(ThePass,TheCrypted, AUTH_SIZE); vpw->pw_passwd = TheCrypted; vpw->pw_clear_passwd = ThePass; vauth_setpw(vpw, TheDomain); }#else if ( vpw->pw_passwd==NULL||vpw->pw_passwd[0]==0) { snprintf(LogLine, sizeof(LogLine), "%s: user has no password %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(15); }#endif /* Encrypt the clear text password using the crypted * password as the salt then * check if it matches the encrypted password * If it does not match, log errors if requested and exit */ if ( (cramaccepted != 0 ) && (apopaccepted != 0 ) && vauth_crypt(TheUser, TheDomain, ThePass, vpw) != 0 ) { if ( ENABLE_LOGGING==1||ENABLE_LOGGING==2){ snprintf(LogLine, sizeof(LogLine), "%s: password fail %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); } else if ( ENABLE_LOGGING==3||ENABLE_LOGGING==4){ snprintf(LogLine, sizeof(LogLine), "%s: password fail (pass: '%s') %s@%s:%s", VchkpwLogName, ThePass, TheUser, TheDomain, IpAddr); } else { LogLine[0] = 0; } vlog( VLOG_ERROR_PASSWD, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(3); }#ifdef ENABLE_LEARN_PASSWORDS#ifdef CLEAR_PASS /* User with pw_clear_passwd unset but pw_passwd set * should have the pw_clear_passwd field filled in */ if ( vpw->pw_clear_passwd==NULL||vpw->pw_clear_passwd[0]==0) { vpw->pw_clear_passwd = ThePass; vauth_setpw(vpw, TheDomain); }#endif#endif /* They are authenticated now, check for restrictions * Check if they are allowed pop access */ if ( ConnType == POP_CONN && (vpw->pw_flags & NO_POP)) { snprintf(LogLine, sizeof(LogLine), "%s: pop access denied %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_ACCESS, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(1); } /* Check if they are allowed smtp access */ else if ( ConnType == SMTP_CONN && (vpw->pw_flags & NO_SMTP)) { snprintf(LogLine, sizeof(LogLine), "%s: smtp access denied %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_ACCESS, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(1); } /* Check if they are allowed imap access */ else if ( ConnType == IMAP_CONN && (vpw->pw_flags & NO_IMAP)) { snprintf(LogLine, sizeof(LogLine), "%s: imap access denied %s@%s:%s", VchkpwLogName, TheUser, TheDomain, IpAddr); vlog(VLOG_ERROR_ACCESS, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(1); } /* show success but with no password */ if ( ENABLE_LOGGING == 1 || ENABLE_LOGGING == 4) { snprintf(LogLine, sizeof(LogLine), "%s: (%s) login success %s@%s:%s", VchkpwLogName, AuthType, TheUser, TheDomain, IpAddr); vlog(VLOG_AUTH, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); } /* If authentication logging is enabled * update the authentication time on the account */#ifdef ENABLE_AUTH_LOGGING vset_lastauth(TheUser,TheDomain,IpAddr);#endif#ifdef POP_AUTH_OPEN_RELAY /* Check if we should open up relay for this account * there is no need to open up relay for smtp authentication */ if ( (vpw->pw_flags & NO_RELAY)==0 && (ConnType != SMTP_CONN) ) { open_smtp_relay(); }#endif /* Save the directory pointer */ pw_dir = vpw->pw_dir;}#ifdef ENABLE_PASSWDvoid login_system_user(){#ifdef HAS_SHADOW struct spwd *spw;#endif struct passwd *pw; if ((pw=getpwnam(TheUser)) == NULL ) { snprintf(LogLine, sizeof(LogLine), "%s: system user not found %s:%s", VchkpwLogName, TheUser, IpAddr); vlog(VLOG_ERROR_LOGON, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(21); }#ifdef HAS_SHADOW if ((spw = getspnam(TheUser)) == NULL) { snprintf(LogLine, sizeof(LogLine), "%s: system user shadow entry not found %s:%s", VchkpwLogName, TheName, IpAddr); vlog(VLOG_ERROR_LOGON, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(22); } if ( strcmp(crypt(ThePass,spw->sp_pwdp),spw->sp_pwdp) != 0 ) {#else if ( strcmp(crypt(ThePass,pw->pw_passwd),pw->pw_passwd) != 0 ) {#endif if (ENABLE_LOGGING==1||ENABLE_LOGGING==2) { snprintf(LogLine, sizeof(LogLine), "%s: system password fail %s:%s", VchkpwLogName, TheName, IpAddr); } else if (ENABLE_LOGGING==3||ENABLE_LOGGING==4) { snprintf(LogLine, sizeof(LogLine), "%s: system password fail (pass: '%s') %s:%s", VchkpwLogName, ThePass, TheName, IpAddr); } else { LogLine[0] = 0; } vlog(VLOG_ERROR_PASSWD, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); vchkpw_exit(23); } pw_uid = pw->pw_uid; pw_gid = pw->pw_gid; pw_dir = pw->pw_dir; /* show success but with no password */ if ( ENABLE_LOGGING == 1 || ENABLE_LOGGING == 4) { snprintf(LogLine, sizeof(LogLine), "%s: system password login success %s:%s", VchkpwLogName, TheUser, IpAddr); vlog(VLOG_AUTH, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine); }#ifdef POP_AUTH_OPEN_RELAY if ( ConnType != SMTP_CONN ) { open_smtp_relay(); }#endif}#endifvoid vchkpw_exit(int err){ if ( ENABLE_LOGGING > 0 ) closelog(); vclose(); exit(err);}/* log messages and figure out what type they are and where * they should go depending on configure options * any one of the pointers can be null, i.e. the information is not available * messages are autmatically cleaned for syslog if it is necessary */void vlog(int verror, char *TheUser, char *TheDomain, char *ThePass, char *TheName, char *IpAddr, char *LogLine) { /* always log to syslog if enabled */ if ( (verror == VLOG_ERROR_PASSWD) && ( ENABLE_LOGGING==1 || ENABLE_LOGGING==2 || ENABLE_LOGGING==3 || ENABLE_LOGGING==4 ) ) { syslog(LOG_NOTICE,sysc(LogLine)); } else if ( verror == VLOG_ERROR_INTERNAL ) { syslog(LOG_NOTICE, sysc(LogLine)); } else if ( verror == VLOG_ERROR_LOGON ) { syslog(LOG_NOTICE, sysc(LogLine)); } else if ( verror == VLOG_ERROR_ACCESS ) { syslog(LOG_NOTICE, sysc(LogLine)); } else if ( verror == VLOG_AUTH && ( ENABLE_LOGGING == 1 || ENABLE_LOGGING == 4 ) ) { syslog(LOG_NOTICE, sysc(LogLine)); }#ifdef ENABLE_MYSQL_LOGGING /* always log to mysql if mysql logging is enabled and it * is not internal error */ if ( (verror == VLOG_ERROR_PASSWD) && ( ENABLE_LOGGING==1 || ENABLE_LOGGING==2 || ENABLE_LOGGING==3 || ENABLE_LOGGING==4 ) ) { if ( (logmysql(verror, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine) ) != 0 ) { syslog(LOG_NOTICE,"vchkpw: can't write MySQL logs"); } } else if ( verror == VLOG_ERROR_INTERNAL ) { if ( (logmysql(verror, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine) ) != 0 ) { syslog(LOG_NOTICE,"vchkpw: can't write MySQL logs"); } } else if ( verror == VLOG_ERROR_LOGON ) { if ( (logmysql(verror, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine) ) != 0 ) { syslog(LOG_NOTICE,"vchkpw: can't write MySQL logs"); } } else if ( verror == VLOG_ERROR_ACCESS ) { if ( (logmysql(verror, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine) ) != 0 ) { syslog(LOG_NOTICE,"vchkpw: can't write MySQL logs"); } } else if ( verror == VLOG_AUTH && ( ENABLE_LOGGING == 1 || ENABLE_LOGGING == 4 ) ) { if ( (logmysql(verror, TheUser, TheDomain, ThePass, TheName, IpAddr, LogLine) ) != 0 ) { syslog(LOG_NOTICE,"vchkpw: can't write MySQL logs"); } }#endif}int authcram(unsigned char *response, unsigned char *challenge, unsigned char *password){ unsigned char digest[16]; unsigned char digascii[33]; unsigned char h; int j; hmac_md5( challenge, strlen(challenge), password, strlen(password), digest); digascii[32]=0; for (j=0;j<16;j++) { h=digest[j] >> 4; digascii[2*j]=hextab[h]; h=digest[j] & 0x0f; digascii[(2*j)+1]=hextab[h]; } /* printf("digascii: %s, response: %s", digascii, response); */ return(strcmp(digascii,response));}int authapop(unsigned char *password, unsigned char *timestamp, unsigned char *clearpass){#ifdef USE_ACTIVE_DIR return(-1);#else MD5_CTX context; unsigned char digest[16]; char encrypted[16*2+1]; char *s; int i; MD5Init(&context); MD5Update(&context, timestamp, strlen(timestamp)); MD5Update(&context, clearpass, strlen(clearpass)); MD5Final(digest, &context); s = encrypted; for (i = 0; i < sizeof(digest); ++i) { *s = hextab[digest[i]/16]; ++s; *s = hextab[digest[i]%16]; ++s; } *s = '\0'; return strcmp(password,encrypted);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -