#include #include #include #include #include #include #include #include #define CLEAN 0 // clean execution of parent and child #define CREDFILE 3 // Credentials file from qmail-smtpd #define DAUNAVAIL -10 // doveadm unavailable #define FRKFAIL -11 // fork failed #define EXECFAIL -12 // child executable failed #define CREDFAIL -13 // Failed to read credentials from fd 3 #define UPFAIL -14 // Failed to read user #define PASSFAIL -15 // Failed to read password #define CHALFAIL -16 // Failed to read challenge #define DOMFAIL -17 // Failed to read domain #define AUTHSIZE 1000 char buf[AUTHSIZE]; char *user = NULL; char *pass = NULL; char *chal = NULL; char *host = NULL; char *dom = NULL; int port; void read_credentials(); char *itoa( int port, char *ldapport ); int auth(char *username,char *password,char *host,char *domain,int *port); int main( int argc, char *argv[] ) { openlog("qldapauth",LOG_PID,LOG_MAIL); host = getenv("LDAP_HOST"); port = atoi( (getenv("LDAP_PORT")) ? : ""); read_credentials(); int authret = auth(user, pass, host, dom, &port); closelog(); exit(authret); } // Read username and password from fd 3, qmail-smtpd void read_credentials() { memset(buf,'\0',AUTHSIZE); ssize_t bufsz = read(CREDFILE,buf,AUTHSIZE); if ( bufsz <= 0 ) { syslog(LOG_INFO,"Failure reading credentials for fd 3"); exit(CREDFAIL);} close(CREDFILE); buf[strchr(buf,'@')-buf] = '\0'; user=buf; if ( strchr(user,'\0') ) dom=(strchr(user,'\0'))+1; if ( strchr(dom,'\0') ) pass=(strchr(dom,'\0'))+1; if ( strchr(pass,'\0') ) chal=(strchr(pass,'\0'))+1; } int auth(char *username,char *password,char *host,char *domain,int *port) { // Security Guards if (!username || !password || !host || !domain || *port == 0) { syslog(LOG_NOTICE,"Missing value(s): username, password, host, domain or port"); return LDAP_OTHER; } // Declarations int conn_status, version(LDAP_VERSION3), bind, unbind; LDAP *ld; char email[200]; char ldapurl[300]; char ldapport[4]; // ldap url memset(ldapurl,'\0',sizeof(ldapurl)); strcpy(ldapurl,"ldap://"); strcat(ldapurl,host); strcat(ldapurl,":"); strcat(ldapurl,itoa(*port,ldapport)); conn_status = ldap_initialize(&ld, ldapurl); if (conn_status != LDAP_SUCCESS) { syslog(LOG_NOTICE,"Error Code = %d, Message = %s",conn_status,ldap_err2string(conn_status)); } ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); // Append domain to username memset(email,'\0',sizeof(email)); strcpy(email,username); strcat(email,"@"); strcat(email,domain); // Execute bind berval credentials; berval *srv = NULL; credentials.bv_val = password; credentials.bv_len = strlen(password); char *remote = getenv("TCPREMOTEIP"); if ( !remote ) remote = (char*)"UNKNOWN HOST"; if ( ( bind = ldap_sasl_bind_s(ld,email,LDAP_SASL_SIMPLE,&credentials,NULL,NULL,&srv) ) == LDAP_SUCCESS ) { syslog(LOG_NOTICE,"Auth succeded for: %s:%s",email,remote); if ( ( unbind = ldap_unbind_ext_s(ld, NULL, NULL) ) != LDAP_SUCCESS) { syslog(LOG_NOTICE,"Unbind failed. Error Code: %d, Message: %s",unbind,ldap_err2string(bind)); } } else { syslog(LOG_NOTICE,"Auth failed for %s:%s, Error Code: %d, Message: %s",email,remote,bind,ldap_err2string(bind)); } return bind; } char * itoa( int port, char *ldapport ) { sprintf(ldapport,"%d",port); return ldapport; }