Hi!
VpopmailD - is very useful for many function. May be in future mail will be delivered via this daemon too =)) I write check_user patch for vpopmaild (as source of ideas was used chkuser of Antonio Nati). Also i rewrite a little access levels systems, for centralized access control... and help command for show only available for current access level commands. This batch seems work, but not tested very careful - any suggestions will be welcome.
After weekends i will try to add command for check quotas.
--- vpopmail-5.4.16.orig/vpopmaild.c    2006-01-17 22:20:47.000000000 +0300
+++ vpopmail-5.4.16/vpopmaild.c 2006-06-09 20:00:07.000000000 +0400
@@ -66,6 +66,7 @@
 char TmpDomain[AUTH_SIZE];
 
 int compact_output = 0;
+int logged_in = 0;
 
 int login();
 int add_user();
@@ -101,6 +102,7 @@
 int mod_list();
 int quit();
 int help();
+int check_user();
 
 /* utility functions */
 void send_user_info(struct vqpasswd *tmpvpw);
@@ -118,47 +120,58 @@
  char *command;
  int (*func)();
  char *help;
+ int access_level;
 } func_t;
 
 /*
-{"login", login, "[EMAIL PROTECTED] password<crlf>" },
+{"login", login, "[EMAIL PROTECTED] password<crlf>", access },
 */
 
+#define ACCESS_ANONYMOUS 1
+#define ACCESS_USER 2
+#define ACCESS_QA_ADMIN 4
+#define ACCESS_SA_ADMIN 8
+#define ACCESS_AUTHORIZED ACCESS_USER | ACCESS_QA_ADMIN | ACCESS_SA_ADMIN
+#define ACCESS_ANYONE ACCESS_ANONYMOUS | ACCESS_AUTHORIZED
+#define ACCESS_ADMINS ACCESS_QA_ADMIN | ACCESS_SA_ADMIN
+
 func_t Functions[] = {
-{"add_user", add_user, "[EMAIL PROTECTED] password<crlf>" },
-{"del_user", del_user, "[EMAIL PROTECTED]<crlf>" },
-{"mod_user", mod_user, "[EMAIL PROTECTED] (option lines)<crlf>.<crlf>" },
-{"user_info", user_info, "user_domain<crlf>" },
-{"add_alias_domain", add_alias_domain, "domain alias<crlf>" },
-{"add_domain", add_domain, "domain [EMAIL PROTECTED]<crlf>" },
-{"del_domain", del_domain, "domain<crlf>" },
-{"dom_info", dom_info, "domain<crlf>" },
-{"mk_dir", mk_dir, "/full/path/to/dir<crlf>" },
-{"rm_dir", rm_dir, "/full/path/to/dir<crlf>" },
-{"list_dir", list_dir, "/full/path/to/dir<crlf>" },
-{"rm_file", rm_file, "/full/path/to/file<crlf>" },
-{"write_file", write_file, "/full/path (data lines)<crlf>.<crlf>" },
-{"read_file", read_file, "/full/path<crlf>" },
-{"list_domains", list_domains, "[page per_page]<crlf>" },
-{"find_domain", find_domain, "domain [per-page]<crlf>" },
-{"domain_count", domain_count, "<crlf>" },
-{"list_users", list_users, "domain<crlf>" },
-{"list_alias", list_alias, "domain<crlf>" },
-{"list_lists", list_lists, "domain<crlf>" },
-{"get_ip_map", get_ip_map, "domain<crlf>" },
-{"add_ip_map", add_ip_map, "domain ip<crlf>" },
-{"del_ip_map", del_ip_map, "domain<crlf>" },
-{"show_ip_map", show_ip_map, "domain<crlf>" },
-{"get_limits", get_limits, "domain<crlf>" },
-{"set_limits", set_limits, "domain (option lines)<crlf>.<crlf>"},
-{"del_limits", del_limits, "domain<crlf>" },
-{"get_lastauth", get_lastauth, "[EMAIL PROTECTED]<crlf>" },
-{"add_list", add_list, "domain listname (command line options)<crlf>" },
-{"del_list", del_list, "domain listname<crlf>"},
-{"mod_list", mod_list, "domain listname (command line options)<crlf>" },
-{"quit", quit, "quit" },
-{"help", help, "help" },
-{NULL, NULL } };
+{"add_user", add_user, "[EMAIL PROTECTED] password<crlf>", ACCESS_ADMINS },
+{"del_user", del_user, "[EMAIL PROTECTED]<crlf>", ACCESS_ADMINS },
+{"mod_user", mod_user, "[EMAIL PROTECTED] (option lines)<crlf>.<crlf>", 
ACCESS_AUTHORIZED },
+{"user_info", user_info, "user_domain<crlf>", ACCESS_ADMINS },
+{"add_alias_domain", add_alias_domain, "domain alias<crlf>", ACCESS_SA_ADMIN },
+{"add_domain", add_domain, "domain [EMAIL PROTECTED]<crlf>", ACCESS_SA_ADMIN },
+{"del_domain", del_domain, "domain<crlf>", ACCESS_SA_ADMIN },
+{"dom_info", dom_info, "domain<crlf>", ACCESS_SA_ADMIN },
+{"mk_dir", mk_dir, "/full/path/to/dir<crlf>", ACCESS_AUTHORIZED },
+{"rm_dir", rm_dir, "/full/path/to/dir<crlf>", ACCESS_AUTHORIZED },
+{"list_dir", list_dir, "/full/path/to/dir<crlf>", ACCESS_AUTHORIZED },
+{"rm_file", rm_file, "/full/path/to/file<crlf>", ACCESS_AUTHORIZED },
+{"write_file", write_file, "/full/path (data lines)<crlf>.<crlf>", 
ACCESS_AUTHORIZED },
+{"read_file", read_file, "/full/path<crlf>", ACCESS_AUTHORIZED },
+{"list_domains", list_domains, "[page per_page]<crlf>", ACCESS_SA_ADMIN },
+{"find_domain", find_domain, "domain [per-page]<crlf>", ACCESS_SA_ADMIN },
+{"domain_count", domain_count, "<crlf>", ACCESS_SA_ADMIN },
+{"list_users", list_users, "domain<crlf>", ACCESS_ADMINS },
+{"list_alias", list_alias, "domain<crlf>", ACCESS_ADMINS },
+{"list_lists", list_lists, "domain<crlf>", ACCESS_ADMINS },
+{"get_ip_map", get_ip_map, "domain<crlf>", ACCESS_ANYONE },
+{"add_ip_map", add_ip_map, "domain ip<crlf>", ACCESS_SA_ADMIN },
+{"del_ip_map", del_ip_map, "domain<crlf>", ACCESS_SA_ADMIN },
+{"show_ip_map", show_ip_map, "domain<crlf>", ACCESS_SA_ADMIN },
+{"get_limits", get_limits, "domain<crlf>", ACCESS_AUTHORIZED },
+{"set_limits", set_limits, "domain (option lines)<crlf>.<crlf>", ACCESS_ADMINS 
},
+{"del_limits", del_limits, "domain<crlf>", ACCESS_SA_ADMIN },
+{"get_lastauth", get_lastauth, "[EMAIL PROTECTED]<crlf>", ACCESS_AUTHORIZED },
+{"add_list", add_list, "domain listname (command line options)<crlf>", 
ACCESS_ADMINS },
+{"del_list", del_list, "domain listname<crlf>", ACCESS_ADMINS },
+{"mod_list", mod_list, "domain listname (command line options)<crlf>", 
ACCESS_ADMINS },
+{"quit", quit, "", ACCESS_ANYONE },
+{"help", help, "", ACCESS_ANYONE },
+{"login", login, "[EMAIL PROTECTED] password [compact]", ACCESS_ANONYMOUS },
+{"check_user", check_user, "[EMAIL PROTECTED]<crlf>", ACCESS_ANYONE },
+{NULL, NULL, NULL, 0 } };
 
 
 int wait_read()
@@ -207,7 +220,7 @@
  int read_size;
  char *command;
  int i;
- int found;
+ int found,accpass;
 
   if( vauth_open( 1 )) {
       snprintf(WriteBuf,sizeof(WriteBuf),
@@ -219,23 +232,6 @@
   snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
   wait_write();
 
-  read_size = wait_read();
-  if ( read_size < 0 ) {
-    snprintf(WriteBuf,sizeof(WriteBuf), 
-      RET_ERR "XXX read timeout" RET_CRLF);
-    wait_write();
-    exit(-1);
-  } 
-
-  /* authenticate first or drop connection */
-  if ( login() < 0 ) {
-    wait_write();
-    vclose();
-    exit(-1);
-  } else {
-    wait_write();
-  }
-
   while(1) {
     read_size = wait_read();
     if ( read_size < 0 ) {
@@ -255,6 +251,22 @@
     for(found=0,i=0;found==0&&Functions[i].command!=NULL;++i ) {
       if ( strcasecmp(Functions[i].command, command) == 0 ) { 
         found = 1;
+        accpass = 0;
+        if (!logged_in && !(Functions[i].access_level & ACCESS_ANONYMOUS)) {
+             snprintf(WriteBuf, sizeof(WriteBuf), 
+                RET_ERR "XXX authorization first" RET_CRLF);
+             continue;
+        }
+        
+        if (Functions[i].access_level & ACCESS_ANONYMOUS) accpass = 1;
+        if (logged_in && Functions[i].access_level & ACCESS_USER) accpass = 1; 
// users can access
+        if (logged_in && AuthVpw.pw_gid & QA_ADMIN && 
Functions[i].access_level & ACCESS_QA_ADMIN) accpass = 1;
+        if (logged_in && AuthVpw.pw_gid & SA_ADMIN && 
Functions[i].access_level & ACCESS_SA_ADMIN) accpass = 1;
+        if (!accpass) {
+           snprintf(WriteBuf, sizeof(WriteBuf),
+                RET_ERR "XXX Permission denied for use this command" RET_CRLF);
+           continue;
+        }
         Functions[i].func();
       }
     }
@@ -269,26 +281,12 @@
 
 int login()
 {
- char *command;
  char *email;
  char *pass;
  char *param;
  uid_t uid;
  gid_t gid;
 
-
-  if ((command=strtok(ReadBuf,TOKENS))==NULL) {
-    snprintf(WriteBuf, sizeof(WriteBuf), 
-      RET_ERR "XXX authorization first" RET_CRLF);
-    return(-1);
-  }
-
-  if (strcasecmp(command, "login" ) != 0 ) {
-    if (strcasecmp(command, "help") == 0 ) help();
-    snprintf(WriteBuf, sizeof(WriteBuf), 
-      RET_ERR "XXX authorization first" RET_CRLF);
-    return(-1);
-  }
   if ((email=strtok(NULL,TOKENS))==NULL) {
     snprintf(WriteBuf, sizeof(WriteBuf), 
       RET_ERR "XXX email address required" RET_CRLF);
@@ -366,6 +364,7 @@
   send_user_info(&AuthVpw);
 
   snprintf(WriteBuf, sizeof(WriteBuf), "." RET_CRLF);
+  logged_in = 1;
   return(0);
   
 }
@@ -2236,15 +2235,24 @@
 
 int help()
 {
- int i;
+ int i,accpass;
 
   snprintf(WriteBuf,sizeof(WriteBuf), RET_OK_MORE);
   wait_write();
 
-  snprintf(WriteBuf,sizeof(WriteBuf),"login [EMAIL PROTECTED] password" 
RET_CRLF);
-  wait_write();
+  //snprintf(WriteBuf,sizeof(WriteBuf),"login [EMAIL PROTECTED] password" 
RET_CRLF);
+  //wait_write();
 
   for(i=0;Functions[i].command!=NULL;++i ) {
+
+    accpass = 0;
+    if (!logged_in && !(Functions[i].access_level & ACCESS_ANONYMOUS)) 
continue;
+    if (Functions[i].access_level & ACCESS_ANONYMOUS) accpass = 1;
+    if (logged_in && Functions[i].access_level & ACCESS_USER) accpass = 1; // 
users can access
+    if (logged_in && AuthVpw.pw_gid & QA_ADMIN && Functions[i].access_level & 
ACCESS_QA_ADMIN) accpass = 1;
+    if (logged_in && AuthVpw.pw_gid & SA_ADMIN && Functions[i].access_level & 
ACCESS_SA_ADMIN) accpass = 1;
+    if (!accpass) continue;
+
     snprintf(WriteBuf, sizeof(WriteBuf), "%s %s" RET_CRLF, 
       Functions[i].command,
       Functions[i].help );
@@ -2254,6 +2262,131 @@
   return(0); 
 }
 
+int check_user()
+{
+  char *user;
+  char domain[MAX_PW_DOMAIN+1];
+  char *yp;
+  char user_dir[MAX_BUFF];
+  char path[MAX_BUFF];
+  char buf[1024];
+  int readed,offset;
+  FILE *fd;
+  struct vqpasswd *user_passwd = NULL;
+
+  if ((user=strtok(NULL,TOKENS))==NULL) {
+    snprintf(WriteBuf,sizeof(WriteBuf), 
+      RET_ERR "XXX email required" RET_CRLF);
+    return(-1);
+  }
+
+  if (!(yp = strchr(user,'@'))) {
+     snprintf(WriteBuf,sizeof(WriteBuf),
+        RET_ERR "XXX email must be in [EMAIL PROTECTED] format" RET_CRLF);
+     return(-1);
+  }
+  
+  *yp=0;
+  yp++;
+  strncpy(domain, yp, sizeof(domain));
+  
+  // code based on chkuser patch by Antonio Nati 
(http://www.interazioni.it/opensource)
+  // rewriten by Dmitriy MiksIr ([EMAIL PROTECTED])
+
+  if (vget_assign(domain, user_dir, sizeof(user_dir), NULL, NULL) == NULL) {
+       snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX domain not exist" 
RET_CRLF);
+       return(-1);
+  }
+
+  snprintf(path, sizeof(path), "%s/.qmail-default", user_dir);
+  readed = 0;
+
+  fd = fopen(path, "r");
+  if (fd == NULL) {
+       snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX can not open 
.qmail-default" RET_CRLF);
+       return(-1);
+  }
+
+  // size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+  readed = fread(buf, 1, sizeof(buf) - 1, fd);
+  fclose (fd);
+
+  buf[readed] = 0;
+  if (strstr(buf, " " BOUNCE_ALL) == NULL 
+        // uncomment line bottom if want always bounce mail even vpopmail 
setted for delete mail
+        // && strstr(buf, " " DELETE_ALL) == NULL
+      ) {
+      // if in .qmail-default not found bounce string
+      // as result all mail for domain must be recieved
+        snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+        return(0);
+  }
+
+  if (valias_select (user, domain) != NULL) {
+      // alias for [EMAIL PROTECTED] found,pass
+      snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+      return(0);
+  }
+
+  while ((yp = strchr(user,'.'))) *yp = ':';
+  
+  snprintf(path, sizeof(path), "%s/.qmail-%s", user_dir, user);
+  fd = fopen(path, "r");
+  if (fd != NULL) {
+      // path/.qmail-user exists, pass
+      fclose(fd);
+      snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+      return(0);
+  }
+  
+  readed = strlen(user);
+  for (offset = readed - 1; offset > 0; --offset) {
+      if (*(user + offset) == '-') {
+           *(user + offset) = 0;
+           snprintf(path, sizeof(path), "%s/.qmail-%s-default", user_dir, 
user);  
+           *(user + offset) = '-';
+           fd = fopen(path, "r");
+           if (fd != NULL) {
+               // path/.qmail-ext-default exists, pass
+               fclose(fd);
+               snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+               return(0);
+           }
+      }
+  }
+  
+  while ((yp = strchr(user,':'))) *yp = '.';
+
+  user_passwd = vauth_getpw(user, domain);
+
+  if (user_passwd == NULL) {
+      for (offset = 1; offset <= (readed - 1); offset++) {
+          if (*(user + offset) == '-') {
+              *(user + offset) = 0;
+              user_passwd = vauth_getpw(user, domain);
+              *(user + offset) = '-';
+              if (user_passwd != NULL) break;
+          }
+      }
+  }
+
+  if (user_passwd != NULL) {
+      if (user_passwd->pw_gid & BOUNCE_MAIL) {
+           snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX exist, but user 
set flag for bounce all mail" RET_CRLF);
+           return(-1);
+      }
+      snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+      return(0);
+  }
+
+  // ezmlm must be already checked, because it create symlink .qmail-listname 
and .qmail-listname-default
+  // mailman seems be ok too
+
+  snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX User not found" RET_CRLF);
+  return(-1);
+
+}
+
 int bkscandir(const char *dirname,
               struct dirent ***namelist,
             int (*select)(struct dirent *),

Reply via email to