/* * Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "vpopmail.h" #include "vauth.h" #include "voracle.h" #include "vlimits.h" // Variables to control debug output #ifdef VPOPMAIL_DEBUG int show_trace=0; int show_query=0; int dump_data=0; #endif #ifndef SQL_CRSR #define SQL_CRSR struct sql_cursor { unsigned int curocn; void *ptr1; void *ptr2; unsigned int magic; }; typedef struct sql_cursor sql_cursor; typedef struct sql_cursor SQL_CURSOR; #endif /* SQL_CRSR */ /* SQLLIB Prototypes */ extern int sqlcxt (/*_ void **, unsigned int *, struct sqlexd *, struct sqlcxp * _*/); extern int sqlcx2t(/*_ void **, unsigned int , struct sqlexd *, struct sqlcxp * _*/); extern int sqlbuft(/*_ void **, char * _*/); extern int sqlgs2t(/*_ void **, char * _*/); extern int sqlorat(/*_ void **, unsigned int *, void * _*/); typedef struct { unsigned short len; unsigned char arr[1]; } VARCHAR; static int update_open = 0; #define SQL_BUF_SIZE 2048 EXEC SQL BEGIN DECLARE SECTION; char SqlBufRead[SQL_BUF_SIZE]; char SqlBufUpdate[SQL_BUF_SIZE]; char SqlBufCreate[SQL_BUF_SIZE]; time_t Vauthtime; char Vip_addr[18]; char Vpw_name[32]; char Vpw_domain[64]; char Vpw_passwd[40]; uid_t Vpw_uid; uid_t Vpw_gid; char Vpw_gecos[48]; char Vpw_dir[160]; char Vpw_shell[20]; #ifdef CLEAR_PASS char Vpw_clear_passwd[16]; #endif #ifdef VALIAS char Vpw_alias[32]; VARCHAR Vpw_alias_line[255]; #endif int cur_users; int level_cur; int level_max; int level_start0; int level_start1; int level_start2; int level_end0; int level_end1; int level_end2; int level_mod0; int level_mod1; int level_mod2; int level_index0; int level_index1; int level_index2; char the_dir[160]; EXEC SQL END DECLARE SECTION; #define UNAME_LEN 120 #define PWD_LEN 16 VARCHAR username[UNAME_LEN]; VARCHAR password[PWD_LEN]; #define SMALL_BUFF 200 char IUser[SMALL_BUFF]; char IPass[SMALL_BUFF]; char IGecos[SMALL_BUFF]; char IDir[SMALL_BUFF]; char IShell[SMALL_BUFF]; char IClearPass[SMALL_BUFF]; void vcreate_dir_control(char *domain); void vcreate_vlog_table(); #ifdef POP_AUTH_OPEN_RELAY void vcreate_relay_table(); #endif #ifdef VALIAS void vcreate_valias_table(); #endif #ifdef ENABLE_AUTH_LOGGING void vcreate_lastauth_table(); #endif int vdel_limits( char *domain ); void fix_name(char *name); void sql_error(msg) char *msg; { /* printf("\n%s", msg); printf("\n%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); printf("in \"%.*s...\"\n", oraca.orastxt.orastxtl, oraca.orastxt.orastxtc); printf("on line %d of %.*s.\n\n", oraca.oraslnr, oraca.orasfnm.orasfnml, oraca.orasfnm.orasfnmc); */ /* Disable ORACLE error checking to avoid an infinite loop * should another error occur within this routine. */ EXEC SQL WHENEVER SQLERROR CONTINUE; /* Roll back any pending changes and * disconnect from Oracle. EXEC SQL ROLLBACK RELEASE; exit(EXIT_FAILURE); */ } /* * Open a connection to oracle for updates */ int vauth_open_update() { if ( update_open != 0 ) return(0); update_open = 1; putenv(ORACLE_HOME); sprintf((char *) username.arr, "%s@%s", ORACLE_USER, ORACLE_SERVICE); username.len = (unsigned short)strlen((char *) username.arr); strcpy((char *) password.arr, ORACLE_PASSWD); password.len = (unsigned short) strlen((char *) password.arr); EXEC SQL WHENEVER SQLERROR DO sql_error("Erro em ORACLE--\n"); EXEC SQL CONNECT :username IDENTIFIED by :password; verrori = 0; return(0); } int voracle_create_all() { int err; if ( (err=vauth_open_update()) != 0 ) return(err); snprintf(SqlBufCreate, SQL_BUF_SIZE, "create table dir_control ( %s )", DIR_CONTROL_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #ifdef POP_AUTH_OPEN_RELAY vcreate_relay_table(); #endif #ifdef ENABLE_AUTH_LOGGING vcreate_lastauth_table(); #endif #ifdef VALIAS vcreate_valias_table(); #endif #ifdef IP_ALIAS_DOMAINS vcreate_ip_map_table(); #endif return(0); } int voracle_drop_all() { int err; if ( (err=vauth_open_update()) != 0 ) return(err); snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table vpopmail"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table dir_control"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table relay"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table ip_alias_map"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table lastauth"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; snprintf(SqlBufUpdate,SQL_BUF_SIZE, "drop table valias"); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int vauth_adddomain( char *domain ) { char *tmpstr = NULL; int err; if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); #ifndef MANY_DOMAINS tmpstr = vauth_munch_domain( domain ); #else tmpstr = ORACLE_DEFAULT_TABLE; #endif snprintf(SqlBufUpdate,SQL_BUF_SIZE, "create table %s ( %s )",tmpstr,TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; voracle_create_all(); sprintf(SqlBufUpdate, "insert into dir_control ( \ domain, cur_users, \ level_cur, level_max, \ level_start0, level_start1, level_start2, \ level_end0, level_end1, level_end2, \ level_mod0, level_mod1, level_mod2, \ level_index0, level_index1, level_index2, the_dir ) values ( \ '%s', '0', \ '0', %d, \ '0', '0', '0', \ '%d', '%d', '%d', \ '0', '2', '4', \ '0', '0', '0', \ '')", domain, MAX_DIR_LEVELS, MAX_DIR_LIST-1, MAX_DIR_LIST-1, MAX_DIR_LIST-1); printf("dir control insert: %s\n", SqlBufUpdate); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int vauth_adduser(char *user, char *domain, char *pass, char *gecos, char *dir, int apop ) { char *domstr; char dom_dir[156]; uid_t uid; gid_t gid; char dirbuf[200]; char quota[30]; char Crypted[100]; int err; if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); strncpy( quota, "NOQUOTA", 30 ); #ifndef MANY_DOMAINS domstr = vauth_munch_domain( domain ); #else domstr = ORACLE_DEFAULT_TABLE; #endif if ( domain == NULL || domain[0] == 0 ) { domstr = ORACLE_LARGE_USERS_TABLE; } if ( strlen(domain) <= 0 ) { if ( strlen(dir) > 0 ) { snprintf(dirbuf, SQL_BUF_SIZE, "%s/users/%s/%s", VPOPMAILDIR, dir, user); } else { snprintf(dirbuf, SQL_BUF_SIZE, "%s/users/%s", VPOPMAILDIR, user); } } else { vget_assign(domain, dom_dir, 156, &uid, &gid ); if ( strlen(dir) > 0 ) { snprintf(dirbuf,SQL_BUF_SIZE, "%s/%s/%s", dom_dir, dir, user); } else { snprintf(dirbuf, SQL_BUF_SIZE, "%s/%s", dom_dir, user); } } if ( pass[0] != 0 ) { mkpasswd3(pass,Crypted, 100); } else { Crypted[0] = 0; } qnprintf( SqlBufUpdate, SQL_BUF_SIZE, INSERT, domstr, user, #ifdef MANY_DOMAINS domain, #endif Crypted, apop, gecos, dirbuf, quota #ifdef CLEAR_PASS ,pass #endif ); printf("add user: %s\n", SqlBufUpdate); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; sprintf( SqlBufUpdate, "insert into lastauth ( pw_user, pw_domain, remote_ip, timestamp ) values \ ('%s', '%s', '0.0.0.0', 0 )", user, domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } struct vqpasswd *vauth_getpw(char *user, char *domain) { char *domstr; static struct vqpasswd vpw; static char in_domain[156]; int err; uid_t myuid; uid_t uid; gid_t gid; struct vlimits limits; if ( vget_assign(domain,NULL,156,&uid,&gid) == NULL ) return(NULL); myuid = geteuid(); if ( myuid != 0 && myuid != uid ) return(NULL); verrori = 0; if ( (err=vauth_open_update()) != 0 ) { verrori = err; return(NULL); } lowerit(user); lowerit(domain); memset(in_domain,0,156); strncpy(in_domain, domain, 155); vset_default_domain( in_domain ); #ifndef MANY_DOMAINS domstr = vauth_munch_domain( in_domain ); #else domstr = ORACLE_DEFAULT_TABLE; #endif if ( domstr == NULL || domstr[0] == 0 ) domstr = ORACLE_LARGE_USERS_TABLE; qnprintf(SqlBufRead, SQL_BUF_SIZE, USER_SELECT, domstr, user #ifdef MANY_DOMAINS , in_domain #endif ); /*printf("getpw: %s\n", SqlBufRead);*/ EXEC SQL PREPARE S FROM :SqlBufRead; EXEC SQL DECLARE C CURSOR FOR S; EXEC SQL OPEN C; EXEC SQL FETCH C INTO :Vpw_name, :Vpw_passwd, :Vpw_uid, :Vpw_gid, :Vpw_gecos, :Vpw_dir, :Vpw_shell, :Vpw_clear_passwd; /*printf("sqlcode = %d\n", sqlca.sqlcode);*/ if (sqlca.sqlcode == 1403 || sqlca.sqlcode == -1002 ) { EXEC SQL CLOSE C; EXEC SQL COMMIT; return(NULL); } /*printf("found it\n");*/ vpw.pw_name = Vpw_name; fix_name(vpw.pw_name); vpw.pw_passwd = Vpw_passwd; fix_name(vpw.pw_passwd); vpw.pw_uid = Vpw_uid; vpw.pw_gid = Vpw_gid; vpw.pw_gecos = Vpw_gecos; fix_name(vpw.pw_gecos); vpw.pw_dir = Vpw_dir; fix_name(vpw.pw_dir); vpw.pw_shell = Vpw_shell; fix_name(vpw.pw_shell); #ifdef CLEAR_PASS vpw.pw_clear_passwd = Vpw_clear_passwd; fix_name(vpw.pw_clear_passwd); #endif EXEC SQL CLOSE C; EXEC SQL COMMIT; if ((! vpw.pw_gid && V_OVERRIDE) && (vget_limits (in_domain, &limits) == 0)) { vpw.pw_flags = vpw.pw_gid | vlimits_get_flag_mask (&limits); } else vpw.pw_flags = vpw.pw_gid; return(&vpw); } int vauth_deldomain( char *domain ) { char *tmpstr; int err; if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); #ifndef MANY_DOMAINS tmpstr = vauth_munch_domain( domain ); snprintf( SqlBufUpdate, SQL_BUF_SIZE, "drop table %s", tmpstr); #else tmpstr = ORACLE_DEFAULT_TABLE; qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from %s where pw_domain = '%s'", tmpstr, domain ); #endif EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #ifdef VALIAS valias_delete_domain( domain); #endif #ifdef ENABLE_AUTH_LOGGING qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from lastauth where pw_domain = '%s'", domain ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #endif vdel_limits(domain); return(0); } int vauth_deluser( char *user, char *domain ) { char *tmpstr; int err = 0; if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); #ifndef MANY_DOMAINS if ( domain == NULL || domain[0] == 0 ) { tmpstr = ORACLE_LARGE_USERS_TABLE; } else { tmpstr = vauth_munch_domain( domain ); } #else tmpstr = ORACLE_DEFAULT_TABLE; #endif qnprintf( SqlBufUpdate, SQL_BUF_SIZE, DELETE_USER, tmpstr, user #ifdef MANY_DOMAINS , domain #endif ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #ifdef ENABLE_AUTH_LOGGING qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from lastauth where pw_user = '%s' and pw_domain = '%s'", user, domain ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #endif return(err); } int vauth_setquota( char *username, char *domain, char *quota) { char *tmpstr; int err; if ( strlen(username) > MAX_PW_NAME ) return(VA_USER_NAME_TOO_LONG); #ifdef USERS_BIG_DIR if ( strlen(username) == 1 ) return(VA_ILLEGAL_USERNAME); #endif if ( strlen(domain) > MAX_PW_DOMAIN ) return(VA_DOMAIN_NAME_TOO_LONG); if ( strlen(quota) > MAX_PW_QUOTA ) return(VA_QUOTA_TOO_LONG); if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); #ifndef MANY_DOMAINS tmpstr = vauth_munch_domain( domain ); #else tmpstr = ORACLE_DEFAULT_TABLE; #endif qnprintf( SqlBufUpdate, SQL_BUF_SIZE, SETQUOTA, tmpstr, quota, username #ifdef MANY_DOMAINS , domain #endif ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } struct vqpasswd *vauth_getall(char *domain, int first, int sortit) { char *domstr = NULL; static struct vqpasswd vpw; static int more = 0; int err; vset_default_domain( domain ); #ifdef MANY_DOMAINS domstr = ORACLE_DEFAULT_TABLE; #else domstr = vauth_munch_domain( domain ); #endif if ( first == 1 ) { if ( (err=vauth_open_update()) != 0 ) return(NULL); qnprintf(SqlBufRead, SQL_BUF_SIZE, GETALL, domstr #ifdef MANY_DOMAINS ,domain #endif ); if ( sortit == 1 ) { strncat( SqlBufRead, " order by pw_name", SQL_BUF_SIZE); } /* if (res_read!=NULL) mysql_free_result(res_read_getall); res_read = NULL; if (mysql_query(&mysql_read_getall,SqlBufRead)) { printf("vmysql: sql error[5]: %s\n", mysql_error(&mysql_update)); return(NULL); } if (!(res_read_getall=mysql_store_result(&mysql_read_getall))) { printf("vsql_getpw: store result failed 2\n"); return(NULL); } */ } else if ( more == 0 ) { return(NULL); } memset(IUser, 0, sizeof(IUser)); memset(IPass, 0, sizeof(IPass)); memset(IGecos, 0, sizeof(IGecos)); memset(IDir, 0, sizeof(IDir)); memset(IShell, 0, sizeof(IShell)); memset(IClearPass, 0, sizeof(IClearPass)); vpw.pw_name = IUser; vpw.pw_passwd = IPass; vpw.pw_gecos = IGecos; vpw.pw_dir = IDir; vpw.pw_shell = IShell; vpw.pw_clear_passwd = IClearPass; /* if ((row_getall = mysql_fetch_row(res_read_getall)) != NULL) { strncpy(vpw.pw_name,row_getall[0],SMALL_BUFF); if (row_getall[1]!=0) strncpy(vpw.pw_passwd,row_getall[1],SMALL_BUFF); if (row_getall[2]!=0) vpw.pw_uid = atoi(row_getall[2]); if (row_getall[3]!=0) vpw.pw_gid = atoi(row_getall[3]); if (row_getall[4]!=0) strncpy(vpw.pw_gecos,row_getall[4],SMALL_BUFF); if (row_getall[5]!=0) strncpy(vpw.pw_dir,row_getall[5],SMALL_BUFF); if (row_getall[6]!=0) { strncpy(vpw.pw_shell, row_getall[6],SMALL_BUFF); } #ifdef CLEAR_PASS if (row_getall[7]!=0) { strncpy(vpw.pw_clear_passwd, row_getall[7],SMALL_BUFF); } #endif more = 1; return(&vpw); } more = 0; mysql_free_result(res_read_getall); res_read_getall = NULL; */ return(NULL); } void vauth_end_getall() { /* if ( res_read_getall != NULL ) { mysql_free_result(res_read_getall); } res_read_getall = NULL; */ } char *vauth_munch_domain( char *domain ) { int i; static char tmpbuf[50]; if ( domain == NULL || domain[0] == 0 ) return(domain); for(i=0;domain[i]!=0;++i){ tmpbuf[i] = domain[i]; if ( domain[i] == '.' || domain[i] == '-' ) { tmpbuf[i] = ORACLE_DOT_CHAR; } } tmpbuf[i] = 0; return(tmpbuf); } int vauth_setpw( struct vqpasswd *inpw, char *domain ) { char *tmpstr; uid_t myuid; uid_t uid; gid_t gid; int err; err = vcheck_vqpw(inpw, domain); if ( err != 0 ) return(err); vget_assign(domain,NULL,156,&uid,&gid); myuid = geteuid(); if ( myuid != 0 && myuid != uid ) { return(VA_BAD_UID); } if ( (err=vauth_open_update()) != 0 ) return(err); vset_default_domain( domain ); #ifndef MANY_DOMAINS tmpstr = vauth_munch_domain( domain ); #else tmpstr = ORACLE_DEFAULT_TABLE; #endif qnprintf( SqlBufUpdate,SQL_BUF_SIZE,SETPW, tmpstr, inpw->pw_passwd, inpw->pw_uid, inpw->pw_gid, inpw->pw_gecos, inpw->pw_dir, inpw->pw_shell, #ifdef CLEAR_PASS inpw->pw_clear_passwd, #endif inpw->pw_name #ifdef MANY_DOMAINS ,domain #endif ); /*printf("add user: %s\n", SqlBufUpdate);*/ EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; #ifdef SQWEBMAIL_PASS vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid); #endif return(0); } #ifdef POP_AUTH_OPEN_RELAY void vopen_smtp_relay() { char *ipaddr; time_t mytime; int err; mytime = time(NULL); ipaddr = getenv("TCPREMOTEIP"); if ( ipaddr == NULL ) { return; } if ( ipaddr != NULL && ipaddr[0] == ':') { ipaddr +=2; while(*ipaddr!=':') ++ipaddr; ++ipaddr; } if ( (err=vauth_open_update()) != 0 ) return; qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "insert into relay ( ip_addr, timestamp ) values ( '%s', %d )", ipaddr, (int)mytime); /*fprintf(stderr, "relay: %s\n", SqlBufUpdate);*/ EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } void vupdate_rules(int fdm) { if (vauth_open_update() != 0) return; sprintf(SqlBufUpdate, "select ip_addr from relay"); EXEC SQL PREPARE SF FROM :SqlBufUpdate; EXEC SQL DECLARE CF CURSOR FOR SF; EXEC SQL OPEN CF; for(;;) { EXEC SQL FETCH CF INTO :Vip_addr; if (sqlca.sqlcode == 1403) break; sprintf(SqlBufUpdate, "%s:allow,RELAYCLIENT=\"\"\n", Vip_addr); write(fdm,SqlBufUpdate, strlen(SqlBufUpdate)); } } void vclear_open_smtp(time_t clear_minutes, time_t mytime) { time_t delete_time; int err; if ( (err=vauth_open_update()) != 0 ) return; delete_time = mytime - clear_minutes; snprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from relay where timestamp <= %d", (int)delete_time); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; } void vcreate_relay_table() { if (vauth_open_update() != 0) return; snprintf( SqlBufCreate, SQL_BUF_SIZE, "create table relay ( %s )",RELAY_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } #endif int vmkpasswd( char *domain ) { return(0); } void vclose() { if (update_open == 1 ) { update_open = 0; EXEC SQL ROLLBACK RELEASE; } } #ifdef IP_ALIAS_DOMAINS void vcreate_ip_map_table() { if ( vauth_open_update() != 0 ) return; snprintf(SqlBufCreate, SQL_BUF_SIZE, "create table ip_alias_map ( %s )", IP_ALIAS_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } int vget_ip_map( char *ip, char *domain, int domain_size) { int ret = -1; if ( ip == NULL || strlen(ip) <= 0 ) return(-1); if ( domain == NULL ) return(-2); if ( vauth_open_update() != 0 ) return(-3); qnprintf(SqlBufRead, SQL_BUF_SIZE, "select domain from ip_alias_map where ip_addr = '%s'", ip); if (mysql_query(&mysql_read,SqlBufRead)) { return(-1); } /* if (!(res_read = mysql_store_result(&mysql_read))) { printf("vsql_getpw: store result failed 4\n"); return(-4); } while((row = mysql_fetch_row(res_read))) { ret = 0; strncpy(domain, row[0], domain_size); } mysql_free_result(res_read); res_update = mysql_store_result(&mysql_read); */ return(ret); } int vadd_ip_map( char *ip, char *domain) { if ( ip == NULL || strlen(ip) <= 0 ) return(-1); if ( domain == NULL || strlen(domain) <= 0 ) return(-1); if ( vauth_open_update() != 0 ) return(-1); qnprintf(SqlBufUpdate,SQL_BUF_SIZE, "update ip_alias_map set ip_addr='%s', domain='%s' ", ip, domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int vdel_ip_map( char *ip, char *domain) { if ( ip == NULL || strlen(ip) <= 0 ) return(-1); if ( domain == NULL || strlen(domain) <= 0 ) return(-1); if ( vauth_open_update() != 0 ) return(-1); qnprintf( SqlBufUpdate,SQL_BUF_SIZE, "delete from ip_alias_map where ip_addr = '%s' and domain = '%s'", ip, domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int vshow_ip_map( int first, char *ip, char *domain ) { static int more = 0; if ( ip == NULL ) return(-1); if ( domain == NULL ) return(-1); if ( vauth_open_update() != 0 ) return(-1); if ( first == 1 ) { snprintf(SqlBufRead,SQL_BUF_SIZE, "select ip_addr, domain from ip_alias_map"); /* if (res_read!=NULL) mysql_free_result(res_read); res_read = NULL; if (mysql_query(&mysql_read,SqlBufRead)) { !error!! } if (!(res_read = mysql_store_result(&mysql_read))) { printf("vsql_getpw: store result failed 5\n"); return(0); } */ } else if ( more == 0 ) { return(0); } /* if ((row = mysql_fetch_row(res_read)) != NULL) { strncpy(ip, row[0], 18); strncpy(domain, row[1], 156); more = 1; return(1); } more = 0; mysql_free_result(res_read); res_read = NULL; */ return(0); } #endif int vread_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid) { int found = 0; int i; if ( vauth_open_update() != 0 ) return(-1); qnprintf(SqlBufRead, SQL_BUF_SIZE, "select %s from dir_control where domain = '%s'", DIR_CONTROL_SELECT, domain ); /*printf("read dir control: %s\n", SqlBufRead);*/ EXEC SQL PREPARE SE FROM :SqlBufRead; EXEC SQL DECLARE CE CURSOR FOR SE; EXEC SQL OPEN CE; found = 0; for(;;) { EXEC SQL FETCH CE INTO :cur_users, :level_cur, :level_max, :level_start0, :level_start1, :level_start2, :level_end0, :level_end1, :level_end2, :level_mod0, :level_mod1, :level_mod2, :level_index0, :level_index1, :level_index2, :the_dir; if (sqlca.sqlcode == 1403) break; found = 1; vdir->cur_users = cur_users; vdir->level_cur = level_cur; vdir->level_max = level_max; vdir->level_start[0] = level_start0; vdir->level_start[1] = level_start1; vdir->level_start[2] = level_start2; vdir->level_end[0] = level_end0; vdir->level_end[1] = level_end1; vdir->level_end[2] = level_end2; vdir->level_mod[0] = level_mod0; vdir->level_mod[1] = level_mod1; vdir->level_mod[2] = level_mod2; vdir->level_index[0] = level_index0; vdir->level_index[1] = level_index1; vdir->level_index[2] = level_index2; fix_name(the_dir); strncpy(vdir->the_dir, the_dir, MAX_DIR_NAME); } EXEC SQL CLOSE CE; EXEC SQL COMMIT; if ( found == 0 ) { vcreate_dir_control(domain); vdir->cur_users = 0; for(i=0;ilevel_start[i] = 0; vdir->level_end[i] = MAX_DIR_LIST-1; vdir->level_index[i] = 0; } vdir->level_mod[0] = 0; vdir->level_mod[1] = 2; vdir->level_mod[2] = 4; vdir->level_cur = 0; vdir->level_max = MAX_DIR_LEVELS; vdir->the_dir[0] = 0; } return(0); } int vwrite_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid) { if ( vauth_open_update() != 0 ) return(-1); sprintf(SqlBufUpdate, "update dir_control \ set cur_users = %ld, \ level_cur = %d , level_max = %d , \ level_start0 = %d , level_start1 = %d , level_start2 = %d , \ level_end0 = %d , level_end1 = %d , level_end2 = %d , \ level_mod0 = %d , level_mod1 = %d , level_mod2 = %d , \ level_index0 = %d , level_index1 = %d , level_index2 = %d , \ the_dir = '%s' where domain = '%s'\n", vdir->cur_users, vdir->level_cur, vdir->level_max, vdir->level_start[0], vdir->level_start[1], vdir->level_start[2], vdir->level_end[0], vdir->level_end[1], vdir->level_end[2], vdir->level_mod[0], vdir->level_mod[1], vdir->level_mod[2], vdir->level_index[0], vdir->level_index[1], vdir->level_index[2], vdir->the_dir, domain); /*printf("write dir control: %s\n", SqlBufUpdate);*/ EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } void vcreate_dir_control(char *domain) { if ( vauth_open_update() != 0 ) return; snprintf(SqlBufCreate, SQL_BUF_SIZE, "create table dir_control ( %s )", DIR_CONTROL_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; qnprintf(SqlBufUpdate, SQL_BUF_SIZE, "insert into dir_control ( \ domain, cur_users, \ level_cur, level_max, \ level_start0, level_start1, level_start2, \ level_end0, level_end1, level_end2, \ level_mod0, level_mod1, level_mod2, \ level_index0, level_index1, level_index2, the_dir ) values ( \ '%s', 0, \ 0, %d, \ 0, 0, 0, \ %d, %d, %d, \ 0, 2, 4, \ 0, 0, 0, \ '')\n", domain, MAX_DIR_LEVELS, MAX_DIR_LIST-1, MAX_DIR_LIST-1, MAX_DIR_LIST-1); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; } int vdel_dir_control(char *domain) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf(SqlBufUpdate, SQL_BUF_SIZE, "delete from dir_control where domain = '%s'", domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } #ifdef ENABLE_AUTH_LOGGING int vset_lastauth(char *user, char *domain, char *remoteip ) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "update lastauth set pw_user='%s', pw_domain='%s', \ remote_ip='%s', timestamp=%lu", user, domain, remoteip, time(NULL)); fprintf(stderr, "auth log: %s\n", SqlBufUpdate); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } time_t vget_lastauth(struct vqpasswd *pw, char *domain) { int err; time_t mytime; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "select timestamp from lastauth where pw_user='%s' and pw_domain='%s'", pw->pw_name, domain); EXEC SQL PREPARE SD FROM :SqlBufUpdate; EXEC SQL DECLARE CD CURSOR FOR SD; EXEC SQL OPEN CD; Vauthtime = 0; EXEC SQL FETCH CD INTO :Vauthtime; EXEC SQL CLOSE CD; EXEC SQL COMMIT; mytime = Vauthtime; return(mytime); } char *vget_lastauthip(struct vqpasswd *pw, char *domain) { int err; if ( (err=vauth_open_update()) != 0 ) return(""); memset(Vip_addr,0,sizeof(Vip_addr)); sprintf( SqlBufUpdate, "select remote_ip from lastauth where pw_user='%s' and pw_domain='%s'", pw->pw_name, domain); EXEC SQL PREPARE SX FROM :SqlBufUpdate; EXEC SQL DECLARE CX CURSOR FOR SX; EXEC SQL OPEN CX; EXEC SQL FETCH CX INTO :Vip_addr; EXEC SQL CLOSE CX; EXEC SQL COMMIT; fix_name(Vip_addr); return(Vip_addr); } void vcreate_lastauth_table() { if ( vauth_open_update() != 0 ) return; snprintf( SqlBufCreate, SQL_BUF_SIZE, "create table lastauth ( %s )", LASTAUTH_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } #endif /* ENABLE_AUTH_LOGGING */ #ifdef VALIAS char *valias_select( char *alias, char *domain ) { int err; /* if we can not connect, set the verrori value */ if ( (err=vauth_open_update()) != 0 ) { return(NULL); } qnprintf( SqlBufRead, SQL_BUF_SIZE, "select valias_line from valias \ where alias = '%s' and domain = '%s'", alias, domain ); EXEC SQL PREPARE SC FROM :SqlBufRead; EXEC SQL DECLARE CC CURSOR FOR SC; EXEC SQL OPEN CC; return(valias_select_next()); } char *valias_select_next() { for(;;) { EXEC SQL FETCH CC INTO :Vpw_alias_line; if (sqlca.sqlcode != 0) break; Vpw_alias_line.arr[Vpw_alias_line.len] = '\0'; return(Vpw_alias_line.arr); } EXEC SQL CLOSE CC; EXEC SQL COMMIT; return(NULL); } int valias_insert( char *alias, char *domain, char *alias_line) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); while(*alias_line==' ' && *alias_line!=0) ++alias_line; qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "insert into valias \ ( alias, domain, valias_line ) values ( '%s', '%s', '%s')", alias, domain, alias_line ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int valias_remove( char *alias, char *domain, char *alias_line) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from valias where alias = '%s' \ and valias_line = '%s' and domain = '%s'", alias, alias_line, domain ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int valias_delete( char *alias, char *domain) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from valias where alias = '%s' \ and domain = '%s'", alias, domain ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } int valias_delete_domain( char *domain) { int err; if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "delete from valias where domain = '%s'", domain ); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } void vcreate_valias_table() { if ( vauth_open_update() != 0 ) return; snprintf( SqlBufCreate, SQL_BUF_SIZE, "create table valias ( %s )", VALIAS_TABLE_LAYOUT ); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } char *valias_select_all( char *alias, char *domain ) { int err; if ( (err=vauth_open_update()) != 0 ) return(NULL); sprintf( SqlBufUpdate, "select alias, valias_line from valias where domain = '%s' order by alias", domain ); EXEC SQL PREPARE SB FROM :SqlBufUpdate; EXEC SQL DECLARE CB CURSOR FOR SB; EXEC SQL OPEN CB; return(valias_select_all_next(alias)); } char *valias_select_all_next(char *alias) { for(;;) { EXEC SQL FETCH CB INTO :Vpw_alias, :Vpw_alias_line; if (sqlca.sqlcode == 1403) break; if (sqlca.sqlcode != 0 ) { EXEC SQL CLOSE CB; EXEC SQL COMMIT; vcreate_valias_table(); return(NULL); } Vpw_alias_line.arr[Vpw_alias_line.len] = '\0'; fix_name(Vpw_alias); strcpy(alias, Vpw_alias); return(Vpw_alias_line.arr); } EXEC SQL CLOSE CB; EXEC SQL COMMIT; return(NULL); } #endif #ifdef ENABLE_SQL_LOGGING int logsql(int verror, char *TheUser, char *TheDomain, char *ThePass, char *TheName, char *IpAddr, char *LogLine) { int err; time_t mytime; mytime = time(NULL); if ( (err=vauth_open_update()) != 0 ) return(err); qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "INSERT INTO vlog set user='%s', passwd='%s', \ domain='%s', logon='%s', remoteip='%s', message='%s', \ error=%i, timestamp=%d", TheUser, ThePass, TheDomain, TheName, IpAddr, LogLine, verror, (int)mytime); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return(0); } void vcreate_vlog_table() { if ( vauth_open_update() != 0 ) return; snprintf( SqlBufCreate, SQL_BUF_SIZE, "CREATE TABLE vlog ( %s )", VLOG_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return; } #endif #ifdef ENABLE_ORACLE_LIMITS void vcreate_limits_table() { if ( vauth_open_update() != 0 ) return; snprintf( SqlBufCreate, SQL_BUF_SIZE, "CREATE TABLE limits ( %s )", LIMITS_TABLE_LAYOUT); EXEC SQL PREPARE S FROM :SqlBufCreate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; } int vget_limits( char *domain, struct vlimits *limits ) { int err; /* if we can not connect, set the verrori value */ if ( (err=vauth_open_update()) != 0 ) { return(-1); } qnprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT maxpopaccounts, maxaliases, " "maxforwards, maxautoresponders, maxmailinglists, diskquota, " "defaultquota, disablepop, disableimap, disabledialup, " "disablepasswordchanging, disablewebmail, disablerelay \n" "FROM limits \n" "WHERE domain = '%s'", domain); /* if (mysql_query(&mysql_read,SqlBufRead)) { vcreate_limits_table(); if (mysql_query(&mysql_read,SqlBufRead)) { fprintf(stderr, "vmysql: sql error[j]: %s\n", mysql_error(&mysql_read)); return(-1); } } if (!(res_read = mysql_store_result(&mysql_read))) { fprintf(stderr, "vmysql: store result failed\n"); return -1; } if (mysql_num_rows(res_read) == 0) { fprintf(stderr, "vnysql: can't find limits for domain '%s'\n", domain); return -1; } if ((row = mysql_fetch_row(res_read)) != NULL) { limits->maxpopaccounts = atoi(row[0]); limits->maxaliases = atoi(row[1]); limits->maxforwards = atoi(row[2]); limits->maxautoresponders = atoi(row[3]); limits->maxmailinglists = atoi(row[4]); limits->diskquota = atoi(row[5]); limits->defaultquota = atoi(row[6]); limits->disablepop = atoi(row[7]); limits->disableimap = atoi(row[8]); limits->disabledialup = atoi(row[9]); limits->disablepasswordchanging = atoi(row[10]); limits->disablewebmail = atoi(row[11]); limits->disablerelay = atoi(row[12]); } mysql_free_result(res_read); */ return 0; } int vdel_limits( char *domain ) { qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "DELETE FROM limits WHERE domain = '%s'", domain); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return 0; } int vset_limits( char *domain, struct vlimits *limits ) { int err; /* if we can not connect, set the verrori value */ if ( (err=vauth_open_update()) != 0 ) { return(-1); } qnprintf( SqlBufUpdate, SQL_BUF_SIZE, "REPLACE INTO limits ( " "domain, maxpopaccounts, maxaliases, " "maxforwards, maxautoresponders, maxmailinglists, diskquota, " "defaultquota, disablepop, disableimap, disabledialup, " "disablepasswordchanging, disablewebmail, disablerelay ) \n" "VALUES \n" "('%s', %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", domain, limits->maxpopaccounts, limits->maxaliases, limits->maxforwards, limits->maxautoresponders, limits->maxmailinglists, limits->diskquota, limits->defaultquota, limits->disablepop, limits->disableimap, limits->disabledialup, limits->disablepasswordchanging, limits->disablewebmail, limits->disablerelay); EXEC SQL PREPARE S FROM :SqlBufUpdate; EXEC SQL EXECUTE S; EXEC SQL COMMIT; return 0; } #endif void fix_name(char *name) { int i; for(i=0;name[i]!=0;++i) { if ( name[i] == ' ' ) { name[i] = 0; } } } int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw) { if ( vpw == NULL ) return(-1); return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd)); }