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 *),