#include #include #include #include #include #include #include #include #include #include #include "ad_func.h" void zero_string(char *line, int len) { int x=0; for(;x=65 && line[x]<=90)line[x]+=32; return; } /*begin control file read functions*/ int read_int(const char *filename) { char line[CHAR_MAX]; int x, t, fp; if ((fp = open(filename, O_RDONLY)) == -1) return 0; zero_string(line, sizeof(line)); t=read(fp, line, CHAR_MAX); close(fp); for(x=0;x<=t && x=48&&line[x]<=57)) break; line[x]='\0'; return atoi(line); } char * read_line(const char *filename) { int x, t, fp; char *line; if ((fp = open(filename, O_RDONLY)) == -1) return NULL; line=(char *)malloc(CHAR_MAX); zero_string(line, CHAR_MAX); t=read(fp, line, CHAR_MAX); close(fp); for(x=0;x<=t && xCHAR_MAX) { syslog(AD_LOG_TO | LOG_ERR, "Out of bounds error: %s+%s", ad.home_dir, mailname); return &ad; } if(CONVERT_MAILNAME_TO_LOWERCASE) { strcpy(t,mailname); strtolower(t, CHAR_MAX); strcat(ad.home_dir, t); }else strcat(ad.home_dir, mailname); if((ad.shell=read_line(AD_DEFAULTSHELL_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "Could not retrieve value from file: %s", AD_DEFAULTSHELL_LOC); return &ad; } if(mailname==NULL) { syslog(AD_LOG_TO | LOG_ERR, "UserName is null"); return &ad; } ad.user=(char *)malloc(CHAR_MAX); strcpy(ad.user, mailname); ad.is_complete=1; return &ad; } ad_defs * get_ad_defaults(void) { static ad_defs ad; if((ad.server=read_line(AD_DEFAULT_ADSERVERNAME_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "get_ad_defaults: Could not retrieve value from file: %s", AD_DEFAULT_ADSERVERNAME_LOC); return &ad; } if((ad.general_user=read_line(AD_DEFAULT_ADGENERALUSERDN_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "get_ad_defaults: Could not retrieve value from file: %s", AD_DEFAULT_ADGENERALUSERDN_LOC); return &ad; } if((ad.general_pw=read_line(AD_DEFAULT_ADGENERALUSERPASS_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "get_ad_defaults: Could not retrieve value from file: %s", AD_DEFAULT_ADGENERALUSERPASS_LOC); return &ad; } if((ad.basedn=read_line(AD_DEFAULT_ADBASEDN_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "get_ad_defaults: Could not retrieve value from file: %s", AD_DEFAULT_ADBASEDN_LOC); return &ad; } if((ad.domain=read_line(AD_DEFAULT_ADDOMAIN_LOC))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "get_ad_defaults: Could not retrieve value from file: %s", AD_DEFAULT_ADDOMAIN_LOC); return &ad; } ad.is_complete=1; return &ad; } /*end control file read functions*/ /*begin user/group setting functions*/ int setup_identity(ad_pwd *ad) { gid_t ga[1]; char t[CHAR_MAX]; ga[0]=(gid_t)ad->gid; if(setgroups(1, ga)==-1) return 0; if(setgid((gid_t) ad->gid)!=0) return 0; if(setuid((uid_t) ad->uid)!=0) return 0; if(chdir(ad->home_dir)!=0) { if(CREATE_HOME_DIR) { if(mkdir(ad->home_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)!=0) return 0; syslog(AD_LOG_TO | LOG_WARNING, "Created homedir at: %s", ad->home_dir); if(CREATE_MAILDIR) { if(strlen(QMAIL_MAILDIRMAKE) + strlen(ad->home_dir) + 10 > CHAR_MAX) return 0; sprintf(t, "%s %s/Maildir", QMAIL_MAILDIRMAKE, ad->home_dir); if(system(t)!=0) return 0; syslog(AD_LOG_TO | LOG_WARNING, "Created maildir in: %s", ad->home_dir); if(chdir(ad->home_dir)!=0) return 0; if(system("echo \"./Maildir/\">.qmail")!=0) return 0; syslog(AD_LOG_TO | LOG_WARNING, "Created .qmail file in: %s", ad->home_dir); } syslog(AD_LOG_TO | LOG_WARNING, "File and home directory creation complete: %s", ad->home_dir); } else return 0; } if(setenv("USER", ad->user, 1)!=0) return 0; if(setenv("HOME", ad->home_dir, 1)!=0) return 0; if(setenv("SHELL", ad->shell, 1)!=0) return 0; return 1; } /*end user/group setting functions*/ /*begin LDAP Active Directory functions*/ int ad_setoption(LDAP *ad_conn, int isVersion3) { int version; if(isVersion3 != 1) { version = LDAP_VERSION2; if(ldap_set_option(ad_conn, LDAP_OPT_PROTOCOL_VERSION, &version)!=LDAP_OPT_SUCCESS) return AD_ERROR; else return AD_SUCCESS; }else{ version = LDAP_VERSION3; if(ldap_set_option(ad_conn, LDAP_OPT_PROTOCOL_VERSION, &version)!=LDAP_OPT_SUCCESS) return AD_ERROR; else return AD_SUCCESS; } } LDAP * ad_init(const char *server, int useGC, int useSSL) { LDAP *ad_conn; char istring[CHAR_MAX]; /* allocate the connection */ if(strlen(server)>CHAR_MAX-15) { syslog(AD_LOG_TO | LOG_ERR, "ad_init: Overflow error: ldap%s://%s:%d", (useSSL?"s":""), server, (useGC==1?GC_SSL_PORT:LDAPS_PORT)); return NULL; } sprintf(istring, "ldap%s://%s:%d", (useSSL?"s":""), server, (useGC==1?(useSSL?GC_SSL_PORT:GC_PORT):(useSSL?LDAPS_PORT:LDAP_PORT))); if(ldap_initialize(&ad_conn, istring)!=LDAP_SUCCESS) { syslog(AD_LOG_TO | LOG_ERR, "ad_init: Could not initialize %s %sconnection to AD: %s", (useGC==1?"GC":"LDAP"), (useSSL?"SSL ":""), server); return NULL; } if(ad_setoption(ad_conn, 1)!=AD_SUCCESS) { syslog(AD_LOG_TO | LOG_ERR, "ad_init: Could not set LDAP options"); return NULL; } return ad_conn; } void ad_close(LDAP *ad_conn) { ldap_unbind_s(ad_conn); } int ad_bind(LDAP *ad_conn, const char *binddn, const char *passwd) { int attempt=0, res; /* connect to the LDAP server */ for(;attemptCHAR_MAX) { syslog(AD_LOG_TO | LOG_ERR, "ad_getsam_fulldn: Email address string out of bounds error: username=%s, domain=%s", username, domain); return AD_ERROR; } sprintf(filter, "(&(objectClass=User)(mail=%s%s%s))", username, (ALLOW_WILDCARDS_IN_EMAIL_ADDRESS?"@*":"@"), domain); if(ldap_search_st(ad_conn, base, LDAP_SCOPE_SUBTREE, filter, attr, 0, &timeout, &msg)!=LDAP_SUCCESS) { syslog(AD_LOG_TO | LOG_ERR, "LDAP could not complete search"); return AD_ERROR; } if((res=ldap_count_entries(ad_conn, msg))!=1) { if(res==0) { syslog(AD_LOG_TO | LOG_ERR, "LDAP could find no match for the email address: %s%s%s", username, (ALLOW_WILDCARDS_IN_EMAIL_ADDRESS?"@*":"@"), domain); return AD_ERROR; }else{ syslog(AD_LOG_TO | LOG_ERR, "LDAP returned an invalid number of entries for %s%s%s (%d)", username, (ALLOW_WILDCARDS_IN_EMAIL_ADDRESS?"@*":"@"), domain, ldap_count_entries(ad_conn, msg)); return AD_ERROR; } } if((fe=ldap_first_entry(ad_conn, msg))==NULL) { syslog(AD_LOG_TO | LOG_ERR, "Could not retrieve result entry"); return AD_ERROR; } if((dn=ldap_get_dn(ad_conn, fe))==NULL){ syslog(AD_LOG_TO | LOG_ERR, "LDAP returned null for the dn"); return AD_ERROR; } if(strlen(dn)>=CHAR_MAX){ syslog(AD_LOG_TO | LOG_ERR, "DN exceeded CHAR_MAX length of %d", CHAR_MAX); return AD_ERROR; } strncpy(samdn, dn, CHAR_MAX); samdn[CHAR_MAX-1]='\0'; return AD_SUCCESS; } int ad_verify_user(const char *user, const char *pass) { LDAP * ld; char sam[512]; ad_defs *ad=get_ad_defaults(); if(!ad->is_complete) return AD_ERROR; if((ld=ad_init(ad->server, AD_USE_GC, AD_ONLY_USE_SSL))==0) return AD_ERROR; if(ad_bind(ld, ad->general_user, ad->general_pw)==AD_SUCCESS) { if((ad_getsam_fulldn(ld, ad->basedn, ad->domain, user, sam))==AD_SUCCESS) { ad_close(ld); /*Now that we have the user, lets rebind with them to verify the password*/ if((ld=ad_init(ad->server, AD_USE_GC, AD_ONLY_USE_SSL))!=0) { if(ad_bind(ld, sam, pass)==AD_SUCCESS) { ad_close(ld); return AD_SUCCESS; } } } } ad_close(ld); return AD_ERROR; } int ad_getpw(const char *user) { LDAP * ld; ad_pwd *adp; ad_defs *ad=get_ad_defaults(); char ts[CHAR_MAX], output[CHAR_MAX]; const char *t=ts; int x=0, y=0, z=0; if(!ad->is_complete) return AD_ERROR; if((ld=ad_init(ad->server, AD_USE_GC, AD_ONLY_USE_SSL))==0) return AD_ERROR; if(ad_bind(ld, ad->general_user, ad->general_pw)!=AD_SUCCESS) { ad_close(ld); return AD_ERROR; } if((ad_getsam_fulldn(ld, ad->basedn, ad->domain, user, ts))!=AD_SUCCESS) { ad_close(ld); return AD_ERROR; } ad_close(ld); adp=getdefault_mailuser(user); if(!ad->is_complete) return AD_ERROR; for(z=0;z<=5;z++) { switch(z) { case 0: t=user; break; case 1: sprintf(ts, "%d", adp->uid); t=ts; break; case 2: sprintf(ts, "%d", adp->gid); t=ts; break; case 3: t=adp->home_dir; break; case 4: ts[0]='\0'; t=ts; case 5: break; } for(y=0;t[y]!='\0' && x