⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vchkpw.c

📁 相当优秀的 UNIX 进程管理工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: vchkpw.c,v 1.11 2004/01/13 15:59:42 tomcollins Exp $ * Copyright (C) 1999-2003 Inter7 Internet Technologies, Inc. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA *  */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <syslog.h>#include <errno.h>#include <sys/wait.h>#include <pwd.h>#include <sys/types.h>#include "config.h"#include "vpopmail.h"#include "vlog.h"#include "vauth.h"#include "vlimits.h"/* for cram-md5 */#include "global.h"#include "md5.h"#include "hmac_md5.h"static char hextab[]="0123456789abcdef";#ifdef HAS_SHADOW#include <shadow.h>#endif/* Definitions */#define VCHKPW_USER     "USER="#define VCHKPW_HOME     "HOME="#define VCHKPW_SHELL    "SHELL=NOLOGIN"#define VCHKPW_VPOPUSER "VPOPUSER="/* For tracking ip of client asking for pop service */char *IpAddr;/* Embed the port in the log when smtp-auth is used */char VchkpwLogName[18];/* For logging, relay info */unsigned int LocalPort;/* storage of authentication information */#define AUTH_SIZE 156#define AUTH_INC_SIZE 155char TheName[AUTH_SIZE];char TheUser[AUTH_SIZE];char ThePass[AUTH_SIZE]; 	/* for C/R this is 'TheResponse' */char TheChallenge[AUTH_SIZE];char TheCrypted[AUTH_SIZE];char TheDomain[AUTH_SIZE];/* log line buffer */#define LOG_LINE_SIZE 500char LogLine[LOG_LINE_SIZE];/* environment variable buffers */#define MAX_ENV_BUF 100static char envbuf1[MAX_ENV_BUF];static char envbuf2[MAX_ENV_BUF];static char envbuf3[MAX_ENV_BUF];static char envbuf4[MAX_ENV_BUF];/* shared data */uid_t pw_uid;gid_t pw_gid;char *pw_dir=NULL;struct vqpasswd *vpw = NULL;/* Forward declaration */char *sysc(char *mess);void login_virtual_user();void login_system_user();void read_user_pass();void vlog(int verror, char *TheUser, char *TheDomain, char *ThePass, char *TheName, char *IpAddr, char *LogLine);void vchkpw_exit(int err);void run_command(char *prog);int authcram(unsigned char *response, unsigned char *challenge, unsigned char *password);int authapop(unsigned char *password, unsigned char *timestamp, unsigned char *clearpass);#define POP_CONN  0#define SMTP_CONN 1#define IMAP_CONN 2int ConnType = 0;int main( int argc, char **argv){ char *tmpstr;  if ( (IpAddr = get_remote_ip())  == NULL) IpAddr="";  if ( (tmpstr = getenv("TCPLOCALPORT")) == NULL) LocalPort = 110;  else LocalPort = atoi(tmpstr);  /* Check which port they are coming in on and    * setup the log name and connection type   */  switch(LocalPort) {    case 25:      strcpy(VchkpwLogName, "vchkpw-smtp");      ConnType = SMTP_CONN;      break;    case 110:      strcpy(VchkpwLogName, "vchkpw-pop3");      ConnType = POP_CONN;      break;    case 143:      strcpy(VchkpwLogName, "vchkpw-imap");      ConnType = IMAP_CONN;      break;    case 465:      strcpy(VchkpwLogName, "vchkpw-smtps");      ConnType = SMTP_CONN;      break;    case 587:      strcpy(VchkpwLogName, "vchkpw-submission");      ConnType = SMTP_CONN;      break;    case 993:      strcpy(VchkpwLogName, "vchkpw-imaps");      ConnType = IMAP_CONN;      break;    case 995:      strcpy(VchkpwLogName, "vchkpw-pop3s");      ConnType = POP_CONN;      break;    default:      sprintf(VchkpwLogName, "vchkpw-%u", LocalPort);      /*       * We're running on an unknown port, so it could be any one of       * the three protocols (SMTP, POP or IMAP).  Try to guess the       * protocol based on argv[1].  For SMTP AUTH, argv[1] is usually       * /bin/true.  For IMAP, it's usually imapd (or something like       * that).  Keep the old default of POP.       * Note that the popular Courier-IMAP does not use vchkpw, it       * links libvpopmail directly into its server.       */      if (strstr (argv[1], "true") != NULL)  /* used as STMP AUTH */        ConnType = SMTP_CONN;      else if (strstr (argv[1], "imap") != NULL)  /* used with IMAP */        ConnType = IMAP_CONN;      else  /* default to POP */        ConnType = POP_CONN;      break;  }  /* read in the user name and password from file descriptor 3 */  read_user_pass();  if ( parse_email( TheName, TheUser, TheDomain, AUTH_SIZE) != 0 ) {    snprintf(LogLine, sizeof(LogLine),       "%s: invalid user/domain characters %s:%s",       VchkpwLogName, TheName, IpAddr);    vlog(VLOG_ERROR_PASSWD, TheUser, TheDomain, ThePass,                             TheName, IpAddr, LogLine);        vchkpw_exit(20);  }  /* check if this virtual domain is in the system    * we look in /var/qmail/users/cdb file   * and while we are at it, let's get the domains   * user id and group id.   */  if ( (vpw = vauth_getpw(TheUser, TheDomain)) != NULL ) {    vget_assign(TheDomain,NULL,0,&pw_uid,&pw_gid);    login_virtual_user();#ifdef ENABLE_PASSWD  /* if it is not in the virtual domains    * then check the user in /etc/passwd   */  } else if ( ENABLE_PASSWD == 1 ) {    login_system_user();#endif  } else {    snprintf(LogLine, sizeof(LogLine), "%s: vpopmail user not found %s@%s:%s",             VchkpwLogName, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_LOGON, TheUser, TheDomain, ThePass,                            TheName, IpAddr, LogLine);    vchkpw_exit(3);  }  vclose();  /* The user is authenticated, now setup the environment */   /* Set the programs effective group id */   if ( ConnType != SMTP_CONN && setgid(pw_gid) == -1 ) {    snprintf(LogLine, sizeof(LogLine), "%s: setgid %lu failed errno %d %s@%s:%s",       VchkpwLogName, (long unsigned)pw_gid, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                               TheName, IpAddr, LogLine);    vchkpw_exit(4);  }  /* Set the programs effective user id */   if ( ConnType != SMTP_CONN && setuid(pw_uid) == -1 ) {    snprintf(LogLine, sizeof(LogLine), "%s: setuid %lu failed errno %d %s@%s:%s",       VchkpwLogName, (long unsigned)pw_uid, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                                 TheName, IpAddr, LogLine);    vchkpw_exit(5);  }  /* Change to the users Maildir directory    * don't do this for smtp authentication connections   */  if (ConnType != SMTP_CONN &&  chdir(pw_dir) == -1) {    if ( vpw!=NULL) {       if ( vmake_maildir(TheDomain, vpw->pw_dir )!= VA_SUCCESS ) {        snprintf(LogLine, sizeof(LogLine),           "%s: autocreate dir errno %d %s %s@%s:%s",           VchkpwLogName, errno, pw_dir, TheUser, TheDomain, IpAddr);        vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                                   TheName, IpAddr, LogLine);        vchkpw_exit(6);      }      chdir(pw_dir);    } else {      snprintf(LogLine, sizeof(LogLine), "%s: chdir failed errno %d %s %s@%s:%s",         VchkpwLogName, errno, pw_dir, TheUser, TheDomain, IpAddr);      vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                                 TheName, IpAddr, LogLine);      vchkpw_exit(6);    }  }  /* The the USER variable */  snprintf (envbuf1, sizeof(envbuf1), "%s%s", VCHKPW_USER, TheUser);  if ( putenv(envbuf1) == -1 ) {    snprintf(LogLine, sizeof(LogLine),       "%s: putenv(USER) failed errno %d %s@%s:%s",       VchkpwLogName, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                               TheName, IpAddr, LogLine);    vchkpw_exit(7);  }  /* Now HOME */  snprintf (envbuf2, sizeof(envbuf2), "%s%s", VCHKPW_HOME, pw_dir);  if ( putenv(envbuf2) == -1 ) {    snprintf(LogLine, sizeof(LogLine),       "%s: putenv(HOME) failed errno %d %s@%s:%s",       VchkpwLogName, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                               TheName, IpAddr, LogLine);    vchkpw_exit(8);  }  /* Now SHELL */  strncpy(envbuf3,VCHKPW_SHELL,sizeof(envbuf3));  envbuf3[sizeof(envbuf3)-1] = 0;   /* make sure it's NULL terminated */  if ( putenv(envbuf3) == -1 ) {    snprintf(LogLine, sizeof(LogLine),       "%s: putenv(SHELL) failed errno %d %s@%s:%s",       VchkpwLogName, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                               TheName, IpAddr, LogLine);    vchkpw_exit(9);  }  /* Now VPOPUSER */  snprintf (envbuf4, sizeof(envbuf4), "%s%s", VCHKPW_VPOPUSER, TheName);  if ( putenv(envbuf4) == -1 ) {    snprintf(LogLine, sizeof(LogLine),      "%s: putenv(VPOPUSER) failed errno %d %s@%s:%s",       VchkpwLogName, errno, TheUser, TheDomain, IpAddr);    vlog(VLOG_ERROR_INTERNAL, TheUser, TheDomain, ThePass,                               TheName, IpAddr, LogLine);    vchkpw_exit(10);  }  /* close the log connection */  if ( ENABLE_LOGGING > 0 ) closelog();  /* And now a simple way to kick off the next program */  execvp(argv[1],argv+1);  /* all done, time to release resources and go away */   exit(0);}/* clean a buffer for syslog */char *sysc(char *mess){ char *ripper;  for(ripper=mess;*ripper!=0;++ripper) {    if ( *ripper=='%' ) *ripper = '#';  }  return(mess);}void read_user_pass(){ int i,j,l;  /* Read the user and password from file descriptor 3   * use TheDomain variable as temporary storage of the    * full incoming line    */   memset(TheDomain,0,AUTH_SIZE);  for(i=0;i<AUTH_SIZE;i+=j){            /* read a chunk */    j = read(3,&TheDomain[i],AUTH_SIZE-i-1);    /* on error exit out */    if ( j == -1 ) {           fprintf(stderr, "%s: vchkpw is only for talking with qmail-popup and qmail-pop3d. \It is not for runnning on the command line.\n", VchkpwLogName);      vchkpw_exit(11);    } else if ( j == 0 ) {      break;    }  }  /* close the user/pass file descriptor */  close(3);  /* parse out the name */  memset(TheName,0,AUTH_SIZE);  for(l=0;l<AUTH_INC_SIZE;++l){    TheName[l] = TheDomain[l];    if ( TheName[l] == 0 ) break;    if ( l==i ) break;  }  /* parse out the password  (or response or C/R) */  memset(ThePass,0,AUTH_SIZE);  for(j=0,++l;l<AUTH_INC_SIZE;++j,++l){    ThePass[j] = TheDomain[l];    if ( ThePass[j] == 0 ) break;    if ( l==i ) break;  }  /* parse out the challenge */  memset(TheChallenge,0,AUTH_SIZE);  for(j=0,++l;l<AUTH_INC_SIZE;++j,++l){    TheChallenge[j] = TheDomain[l];    if ( TheChallenge[j] == 0 ) break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -