* check_size
Syntax: check_size [EMAIL PROTECTED] requested_size[K|M]
Check quota of user and of domain. If current disk usage plus requested_size more than quota, answer is -ERR, else say +OK

* check_user
Syntax: check_user [EMAIL PROTECTED]
Check exist of [EMAIL PROTECTED] Answer is +OK, if [EMAIL PROTECTED] valid user, alias, maillist. Else, answer is -ERR, if [EMAIL PROTECTED] not exist or user set bounce_all_mail flag.
diff -ur vpopmail-5.4.16.orig/maildirquota.c vpopmail-5.4.16/maildirquota.c
--- vpopmail-5.4.16.orig/maildirquota.c 2006-01-17 22:08:34.000000000 +0300
+++ vpopmail-5.4.16/maildirquota.c      2006-06-15 17:06:33.000000000 +0400
@@ -47,8 +47,8 @@
 static int docheckquota(const char *dir, int *maildirsize_fdptr,
        const char *quota_type, long xtra_size, int xtra_cnt, int *percentage);
 static int docount(const char *, time_t *, off_t *, unsigned *);
-static int maildir_checkquota(const char *dir, int *maildirsize_fdptr,
-       const char *quota_type, long xtra_size, int xtra_cnt);
+//static int maildir_checkquota(const char *dir, int *maildirsize_fdptr,
+//     const char *quota_type, long xtra_size, int xtra_cnt);
 /* moved into maildirquota.h as non-static
 static int maildir_addquota(const char *dir, int maildirsize_fd,
        const char *quota_type, long maildirsize_size, int maildirsize_cnt);
@@ -404,7 +404,7 @@
 }
 
 
-static int maildir_checkquota(const char *dir,
+int maildir_checkquota(const char *dir,
        int *maildirsize_fdptr,
        const char *quota_type,
        long xtra_size,
@@ -477,8 +477,10 @@
                }
                close(maildirsize_fd);
 
-               if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60)
+               if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60) {
+                       free(checkfolder);
                        return (n);
+               }
        }
 
        /* rebuild the maildirsize file */
diff -ur vpopmail-5.4.16.orig/maildirquota.h vpopmail-5.4.16/maildirquota.h
--- vpopmail-5.4.16.orig/maildirquota.h 2005-03-20 20:01:43.000000000 +0300
+++ vpopmail-5.4.16/maildirquota.h      2006-06-15 15:27:41.000000000 +0400
@@ -17,6 +17,8 @@
 int domain_over_maildirquota(const char *userdir);
 int user_over_maildirquota(const char *dir, const char *quota);
 int vmaildir_readquota(const char *dir,        const char *quota);
+int maildir_checkquota(const char *dir, int *maildirsize_fdptr, const char 
*quota_type, long xtra_size, int xtra_cnt);
+
 
 int maildir_addquota(const char *,     /* Pointer to the maildir */
        int,    /* Must be the int pointed to by 2nd arg to checkquota */
diff -ur vpopmail-5.4.16.orig/vpopmaild.c vpopmail-5.4.16/vpopmaild.c
--- vpopmail-5.4.16.orig/vpopmaild.c    2006-01-17 22:20:47.000000000 +0300
+++ vpopmail-5.4.16/vpopmaild.c 2006-06-15 17:45:53.000000000 +0400
@@ -27,6 +27,7 @@
 #include "vpopmail.h"
 #include "vauth.h"
 #include "vlimits.h"
+#include "maildirquota.h"
 
 /* two responses */
 #define RET_OK "+OK \r\n"
@@ -66,6 +67,7 @@
 char TmpDomain[AUTH_SIZE];
 
 int compact_output = 0;
+int logged_in = 0;
 
 int login();
 int add_user();
@@ -101,6 +103,8 @@
 int mod_list();
 int quit();
 int help();
+int check_user();
+int check_size();
 
 /* utility functions */
 void send_user_info(struct vqpasswd *tmpvpw);
@@ -118,47 +122,59 @@
  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 },
+{"check_size", check_size, "[EMAIL PROTECTED] message_size<crlf>", 
ACCESS_ANYONE },
+{NULL, NULL, NULL, 0 } };
 
 
 int wait_read()
@@ -207,7 +223,7 @@
  int read_size;
  char *command;
  int i;
- int found;
+ int found,accpass;
 
   if( vauth_open( 1 )) {
       snprintf(WriteBuf,sizeof(WriteBuf),
@@ -219,23 +235,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 +254,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 +284,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 +367,7 @@
   send_user_info(&AuthVpw);
 
   snprintf(WriteBuf, sizeof(WriteBuf), "." RET_CRLF);
+  logged_in = 1;
   return(0);
   
 }
@@ -2236,15 +2238,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 +2265,213 @@
   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);
+  }
+
+  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_flags & 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);
+  }
+
+  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 = '.';
+
+  // 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 check_size()
+{
+  char *user, *yp;
+  char domain[MAX_PW_DOMAIN+1];
+  char user_dir[MAX_BUFF];
+  char path[MAX_BUFF];
+  char *size;
+  unsigned long asksize,userq,limitq;
+  int userc,i,retv;
+  struct vqpasswd *user_passwd = NULL;
+  struct vlimits limits;
+
+  if ((user=strtok(NULL,TOKENS))==NULL) {
+    snprintf(WriteBuf,sizeof(WriteBuf),
+      RET_ERR "XXX email required" RET_CRLF);
+    return(-1);
+  }
+
+  if ((size=strtok(NULL,TOKENS))==NULL) {
+    snprintf(WriteBuf,sizeof(WriteBuf),
+      RET_ERR "XXX size 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));
+
+  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);
+  }
+
+  user_passwd = vauth_getpw(user, domain);
+  if (user_passwd == NULL) {
+       snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX user not found" 
RET_CRLF);
+       return(-1);
+  }
+  
+  asksize = atol(format_maildirquota(size));
+  
+  if ((strcmp(user_passwd->pw_shell, "NOQUOTA"))) {
+      // quota for user is set
+      int fd = -1;
+      snprintf(path, sizeof(path), "%s/Maildir", user_passwd->pw_dir);
+      for (i=0;i<10;i++) {
+         retv = maildir_checkquota(path, &fd, user_passwd->pw_shell, asksize, 
1);
+         if (fd >= 0) close(fd);
+         if (retv == 0) break;
+         // overquoted
+         if (errno != EAGAIN) {
+             snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX mailbox is over 
quota (Quota: %s)" RET_CRLF, user_passwd->pw_shell);
+             return(-1);
+         }
+         sleep(1);
+      }
+  }
+  if (!(vget_limits(domain, &limits)) && (limits.diskquota != 0 || 
limits.maxmsgcount != 0)) {
+     limitq = limits.diskquota * 1024 * 1024;
+     if (!(readdomainquota(user_dir, &userq, &userc))) {
+        if (limits.diskquota > 0 && (userq + asksize) > limitq) {
+           snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX domain is over 
quota (Quota: %luS)" RET_CRLF, limitq);
+           return(-1);
+        }
+        if (limits.maxmsgcount > 0 && userc >= limits.maxmsgcount) {
+           snprintf(WriteBuf,sizeof(WriteBuf), RET_ERR "XXX domain is over 
quota (Quota: %dC)" RET_CRLF, limits.maxmsgcount);
+           return(-1);
+        }
+     }
+  }
+  
+  snprintf(WriteBuf,sizeof(WriteBuf), RET_OK);
+  return(0);
+}
+
+
 int bkscandir(const char *dirname,
               struct dirent ***namelist,
             int (*select)(struct dirent *),

Reply via email to