1 /*
2 * $Id: vsybase.c 1014 2011-02-03 16:04:37Z volz0r $
3 * Copyright (C) 1999-2009 Inter7 Internet Technologies, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 */
19 #include <pwd.h>
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <string.h>
25 #include <time.h>
26 #include <sybfront.h>
27 #include <sybdb.h>
28 #include "config.h"
29 #include "vpopmail.h"
30 #include "vauth.h"
31 #include "vlimits.h"
32 #include "vsybase.h"
33
34 static int is_open = 0;
35 static LOGINREC *login;
36 static DBPROCESS *dbproc;
37
38 #define SQL_BUF_SIZE 2048
39 static char SqlBuf[SQL_BUF_SIZE];
40 static char SqlBuf1[SQL_BUF_SIZE];
41
42 #define SMALL_BUFF 200
43 char IUser[SMALL_BUFF];
44 char IPass[SMALL_BUFF];
45 char IGecos[SMALL_BUFF];
46 char IDir[SMALL_BUFF];
47 char IShell[SMALL_BUFF];
48
49 void vcreate_relay_table();
50
err_handler(dbproc,severity,dberr,oserr,dberrstr,oserrstr)51 int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
52 DBPROCESS *dbproc;
53 int severity;
54 int dberr;
55 int oserr;
56 char *dberrstr;
57 char *oserrstr;
58 {
59 if ((dbproc == NULL) || (DBDEAD(dbproc))) {
60 return(INT_EXIT);
61 } else {
62 return(INT_CANCEL);
63 }
64 }
65
msg_handler(dbproc,msgno,msgstate,severity,msgtext,srvname,procname,line)66 int msg_handler(dbproc, msgno, msgstate, severity, msgtext,
67 srvname, procname, line)
68
69 DBPROCESS *dbproc;
70 DBINT msgno;
71 int msgstate;
72 int severity;
73 char *msgtext;
74 char *srvname;
75 char *procname;
76 DBUSMALLINT line;
77
78 {
79 return(0);
80 }
81
82
vauth_open(int will_update)83 int vauth_open( int will_update )
84 {
85 #ifdef VPOPMAIL_DEBUG
86 show_trace = ( getenv("VPSHOW_TRACE") != NULL);
87 show_query = ( getenv("VPSHOW_QUERY") != NULL);
88 dump_data = ( getenv("VPDUMP_DATA") != NULL);
89 #endif
90
91 #ifdef VPOPMAIL_DEBUG
92 if( show_trace ) {
93 fprintf( stderr, "vauth_open()\n");
94 }
95 #endif
96
97
98 /*
99 * If the connection to this authentication database can fail
100 * you should test access here. If it works, return 0, else
101 * return VA_NO_AUTH_CONNECTION. You can also set the string
102 * sqlerr to some short descriptive text about the problem,
103 * and allocate a much longer string, pointed to by last_query
104 * that can be displayed in an error message returned because
105 * of this problem.
106 *
107 */
108
109 if ( is_open == 1 ) return(0);
110
111 is_open = 1;
112
113 if ( dbinit() == FAIL ) return(-1);
114
115 dberrhandle(err_handler);
116 dbmsghandle(msg_handler);
117 login=dblogin();
118
119 DBSETLUSER(login, SYBASE_USER);
120 DBSETLPWD(login, SYBASE_PASSWD);
121 DBSETLAPP(login, SYBASE_APP);
122
123 dbproc = dbopen(login,SYBASE_SERVER);
124
125 if ( dbuse(dbproc, SYBASE_DATABASE) == FAIL ) {
126 dbcancel(dbproc);
127
128 snprintf( SqlBuf, sizeof(SqlBuf), "create database %s", SYBASE_DATABASE );
129 dbcmd(dbproc, SqlBuf);
130 dbsqlexec(dbproc);
131 while(dbresults(dbproc) != NO_MORE_RESULTS)
132 continue;
133 dbuse(dbproc, SYBASE_DATABASE);
134
135 }
136 return(0);
137 }
138
vauth_adddomain(char * domain)139 int vauth_adddomain( char *domain )
140 {
141 return(vauth_adddomain_size( domain, SITE_SIZE ));
142 }
143
vauth_adddomain_size(char * domain,int site_size)144 int vauth_adddomain_size( char *domain, int site_size )
145 {
146 char *tmpstr = NULL;
147
148 vauth_open();
149 vset_default_domain( domain );
150
151 if ( site_size == LARGE_SITE ) {
152 tmpstr = vauth_munch_domain( domain );
153 snprintf( SqlBuf1, sizeof (SqlBuf1), "create table %s ( %s )",
154 tmpstr, LARGE_TABLE_LAYOUT );
155 } else {
156 snprintf( SqlBuf1, sizeof (SqlBuf1), "create table %s ( %s )",
157 SYBASE_DEFAULT_TABLE, SMALL_TABLE_LAYOUT);
158 }
159
160 dbcmd(dbproc, SqlBuf1);
161 dbsqlexec(dbproc);
162 while(dbresults(dbproc) != NO_MORE_RESULTS)
163 continue;
164
165 return(0);
166 }
167
168
vauth_adduser(char * user,char * domain,char * pass,char * gecos,char * dir,int apop)169 int vauth_adduser(char *user, char *domain, char *pass, char *gecos,
170 char *dir, int apop )
171 {
172 return(vauth_adduser_size(user, domain, pass, gecos, dir, apop, SITE_SIZE ));
173 }
174
vauth_adduser_size(char * user,char * domain,char * pass,char * gecos,char * dir,int apop,int site_size)175 int vauth_adduser_size(char *user, char *domain, char *pass, char *gecos,
176 char *dir, int apop, int site_size )
177 {
178 char *domstr;
179 int pop;
180 char dom_dir[156];
181 int uid, gid;
182 char dirbuf[200];
183 char quota[30];
184
185 vauth_open();
186 vset_default_domain( domain );
187
188 strncpy( quota, "NOQUOTA", 30 );
189
190 if ( apop == 0 ) {
191 pop = 1;
192 } else {
193 pop = 2;
194 }
195 domstr = vauth_munch_domain( domain );
196 if ( site_size == LARGE_SITE && (domain == NULL || domain[0] == 0) ) {
197 domstr = SYBASE_LARGE_USERS_TABLE;
198 }
199
200 if ( strlen(domain) <= 0 ) {
201 if ( strlen(dir) > 0 ) {
202 snprintf(dirbuf, sizeof(dirbuf), "%s/users/%s/%s", VPOPMAILDIR, dir, user);
203 } else {
204 snprintf(dirbuf, sizeof(dirbuf), "%s/users/%s", VPOPMAILDIR, user);
205 }
206 } else {
207 vget_assign(domain, dom_dir, 156, &uid, &gid );
208 if ( strlen(dir) > 0 ) {
209 snprintf(dirbuf, sizeof(dirbuf), "%s/%s/%s", dom_dir, dir, user);
210 } else {
211 snprintf(dirbuf, sizeof(dirbuf), "%s/%s", dom_dir, user);
212 }
213 }
214
215 if ( site_size == LARGE_SITE ) {
216 qnprintf( SqlBuf, sizeof(SqlBuf), LARGE_INSERT, domstr,
217 user, pass, pop, gecos, dirbuf, quota);
218 } else {
219 qnprintf( SqlBuf, sizeof(SqlBuf), SMALL_INSERT, SYBASE_DEFAULT_TABLE,
220 user, domain, pass, pop, gecos, dirbuf, quota);
221 }
222
223 dbcmd(dbproc, SqlBuf);
224 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
225 if ( site_size == LARGE_SITE ) {
226 vauth_adddomain_size( SYBASE_LARGE_USERS_TABLE, LARGE_SITE );
227
228 dbcmd(dbproc, SqlBuf);
229 if ( dbsqlexec(dbproc)==FAIL || dbresults(dbproc)== FAIL ) {
230 fprintf(stderr, "sybase adduser failed\n");
231 return(-1);
232 }
233 dbcancel(dbproc);
234
235 } else {
236 fprintf(stderr, "sybase adduser failed\n");
237 return(-1);
238 }
239 }
240 dbcancel(dbproc);
241 return(0);
242
243 }
244
vauth_getpw(char * user,char * domain)245 struct vqpasswd *vauth_getpw(char *user, char *domain)
246 {
247 return(vauth_getpw_size( user, domain, SITE_SIZE ));
248 }
249
vauth_getpw_size(char * user,char * domain,int site_size)250 struct vqpasswd *vauth_getpw_size(char *user, char *domain, int site_size)
251 {
252 char in_domain[156];
253 char *domstr;
254 static struct vqpasswd pwent;
255
256 lowerit(user);
257 lowerit(domain);
258
259 snprintf(in_domain, sizeof(in_domain), "%s", domain);
260
261 vauth_open();
262 vset_default_domain( in_domain );
263
264 domstr = vauth_munch_domain( in_domain );
265 if ( domstr == NULL || domstr[0] == 0 ) {
266 domstr = SYBASE_LARGE_USERS_TABLE;
267 }
268
269 if ( site_size == LARGE_SITE ) {
270 qnprintf( SqlBuf, sizeof(SqlBuf), LARGE_SELECT, domstr, user);
271 } else {
272 qnprintf( SqlBuf, sizeof(SqlBuf), SMALL_SELECT, SYBASE_DEFAULT_TABLE, user, in_domain);
273 }
274
275 dbcmd(dbproc, SqlBuf);
276 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
277 printf("vsql_getpw: failed select\n");
278 return(NULL);
279 }
280
281 pwent.pw_name = IUser;
282 pwent.pw_passwd = IPass;
283 pwent.pw_gecos = IGecos;
284 pwent.pw_dir = IDir;
285 pwent.pw_shell = IShell;
286
287 dbbind(dbproc, 1, NTBSTRINGBIND, (DBINT)0, (BYTE *)pwent.pw_name);
288 dbbind(dbproc, 2, NTBSTRINGBIND, (DBINT)0, (BYTE *)pwent.pw_passwd);
289 dbbind(dbproc, 3, INTBIND, (DBINT)0, (BYTE *)&pwent.pw_uid);
290 dbbind(dbproc, 4, INTBIND, (DBINT)0, (BYTE *)&pwent.pw_gid);
291 dbbind(dbproc, 5, NTBSTRINGBIND, (DBINT)0, (BYTE *)pwent.pw_gecos);
292 dbbind(dbproc, 6, NTBSTRINGBIND, (DBINT)0, (BYTE *)pwent.pw_dir);
293 dbbind(dbproc, 7, NTBSTRINGBIND, (DBINT)0, (BYTE *)pwent.pw_shell);
294
295 mem_size = 0;
296 while( dbnextrow(dbproc) != NO_MORE_ROWS ) {
297 ++mem_size;
298 }
299 dbcancel(dbproc);
300 if ( mem_size == 0 ) return(NULL);
301
302 vlimits_setflags (&pwent, in_domain);
303
304 return(&pwent);
305 }
306
vauth_deldomain(char * domain)307 int vauth_deldomain( char *domain )
308 {
309 return(vauth_deldomain_size( domain, SITE_SIZE ));
310 }
311
vauth_deldomain_size(char * domain,int site_size)312 int vauth_deldomain_size( char *domain, int site_size )
313 {
314 char *tmpstr;
315
316 vauth_open();
317 vset_default_domain( domain );
318 tmpstr = vauth_munch_domain( domain );
319
320 if ( site_size == LARGE_SITE ) {
321 snprintf( SqlBuf, sizeof(SqlBuf), "drop table %s", tmpstr);
322 } else {
323 qnprintf( SqlBuf, sizeof(SqlBuf), "delete from %s where pw_domain = '%s'",
324 SYBASE_DEFAULT_TABLE, domain );
325 }
326
327 dbcmd(dbproc, SqlBuf);
328 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
329 return(-1);
330 }
331 dbcancel(dbproc);
332 return(0);
333 }
334
vauth_deluser(char * user,char * domain)335 int vauth_deluser( char *user, char *domain )
336 {
337 return(vauth_deluser_size( user, domain, SITE_SIZE));
338 }
339
vauth_deluser_size(char * user,char * domain,int site_size)340 int vauth_deluser_size( char *user, char *domain, int site_size )
341 {
342 char *tmpstr;
343
344 vauth_open();
345 vset_default_domain( domain );
346
347 if ( site_size == LARGE_SITE ) {
348 if ( domain == NULL || domain[0] == 0 ) {
349 tmpstr = SYBASE_LARGE_USERS_TABLE;
350 } else {
351 tmpstr = vauth_munch_domain( domain );
352 }
353 qnprintf( SqlBuf, sizeof(SqlBuf), "delete from %s where pw_name = '%s'",
354 tmpstr, user );
355 } else {
356 qnprintf( SqlBuf, sizeof(SqlBuf),
357 "delete from %s where pw_name = '%s' and pw_domain = '%s'",
358 SYBASE_DEFAULT_TABLE, user, domain );
359 }
360 dbcmd(dbproc, SqlBuf);
361 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
362 fprintf(stderr, "sybase query\n");
363 return(-1);
364 }
365 dbcancel(dbproc);
366 return(0);
367 }
368
vauth_setquota(char * user,char * domain,char * quota)369 int vauth_setquota( char *user, char *domain, char *quota)
370 {
371 return(vauth_setquota_size( user, domain, quota, SITE_SIZE));
372 }
373
vauth_setquota_size(char * user,char * domain,char * quota,int site_size)374 int vauth_setquota_size( char *user, char *domain, char *quota, int site_size)
375 {
376 char *tmpstr;
377
378 vauth_open();
379 vset_default_domain( domain );
380
381 if ( site_size == LARGE_SITE ) {
382 tmpstr = vauth_munch_domain( domain );
383 qnprintf( SqlBuf, sizeof(SqlBuf),
384 "update %s set pw_shell = '%s' where pw_name = '%s'",
385 tmpstr, quota, user );
386 } else {
387 qnprintf( SqlBuf, sizeof(SqlBuf),
388 "update %s set pw_shell = '%s' where pw_name = '%s' and pw_domain = '%s'",
389 SYBASE_DEFAULT_TABLE, quota, user, domain );
390 }
391 dbcmd(dbproc, SqlBuf);
392 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
393 fprintf(stderr, "sybase query\n");
394 return(-1);
395 }
396 dbcancel(dbproc);
397 return(0);
398 }
399
vauth_vpasswd(char * user,char * domain,char * pass,int apop)400 int vauth_vpasswd( char *user, char *domain, char *pass, int apop )
401 {
402 return(vauth_vpasswd_size( user, domain, pass, apop, SITE_SIZE ));
403 }
404
vauth_vpasswd_size(char * user,char * domain,char * pass,int apop,int site_size)405 int vauth_vpasswd_size( char *user, char *domain, char *pass,
406 int apop, int site_size )
407 {
408 char *tmpstr;
409 uid_t uid;
410 gid_t gid;
411 uid_t myuid;
412
413 myuid = geteuid();
414 vget_assign(domain,NULL,0,&uid,&gid);
415 if (myuid != 0 && myuid != uid ) {
416 return(VA_BAD_UID);
417 }
418
419 vauth_open();
420 vset_default_domain( domain );
421
422 if ( site_size == LARGE_SITE ) {
423 tmpstr = vauth_munch_domain( domain );
424 qnprintf( SqlBuf, sizeof(SqlBuf),
425 "update %s set pw_passwd = '%s' where pw_name = '%s'",
426 tmpstr, pass, user );
427 } else {
428 qnprintf( SqlBuf, sizeof(SqlBuf),
429 "update %s set pw_passwd = '%s' where pw_name = '%s' and pw_domain = '%s'",
430 SYBASE_DEFAULT_TABLE, pass, user, domain );
431 }
432 dbcmd(dbproc, SqlBuf);
433 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
434 fprintf(stderr, "sybase query\n");
435 return(-1);
436 }
437 dbcancel(dbproc);
438 return(0);
439 }
440
vauth_end_getall()441 void vauth_end_getall()
442 {
443 }
444
vauth_getall(char * domain,int first,int sortit)445 struct vqpasswd *vauth_getall(char *domain, int first, int sortit)
446 {
447 return(vauth_getall_size(domain, first, sortit, SITE_SIZE));
448 }
449
vauth_getall_size(char * domain,int first,int sortit,int site_size)450 struct vqpasswd *vauth_getall_size(char *domain, int first, int sortit, int site_size)
451 {
452 char *domstr = NULL;
453 static struct vqpasswd pwent;
454 static int more = 0;
455
456 vset_default_domain( domain );
457
458 if ( site_size == LARGE_SITE ) {
459 domstr = vauth_munch_domain( domain );
460 }
461
462 if ( first == 1 ) {
463 vauth_open();
464
465 if ( site_size == LARGE_SITE ) {
466 qnprintf( SqlBuf, sizeof(SqlBuf), LARGE_GETALL, domstr);
467 } else {
468 qnprintf( SqlBuf, sizeof(SqlBuf), SMALL_GETALL, SYBASE_DEFAULT_TABLE, domain);
469 }
470 if ( sortit == 1 ) {
471 strcat( SqlBuf, " order by pw_name");
472 }
473 dbcmd(dbproc, SqlBuf);
474 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
475 printf("vsql_getpw: failed select\n");
476 return(NULL);
477 }
478 } else if ( more == 0 ) {
479 return(NULL);
480 }
481
482 pwent.pw_name = IUser;
483 pwent.pw_passwd = IPass;
484 pwent.pw_gecos = IGecos;
485 pwent.pw_dir = IDir;
486 pwent.pw_shell = IShell;
487
488 if ( dbnextrow(dbproc) != NO_MORE_ROWS ) {
489 strncpy(pwent.pw_name,(char *)dbretdata(dbproc,1),SMALL_BUFF);
490 strncpy(pwent.pw_passwd,(char *)dbretdata(dbproc,2),SMALL_BUFF);
491 pwent.pw_uid = atoi(dbretdata(dbproc,3));
492 pwent.pw_gid = atoi(dbretdata(dbproc,4));
493 strncpy(pwent.pw_gecos,dbretdata(dbproc,5),SMALL_BUFF);
494 strncpy(pwent.pw_dir,dbretdata(dbproc,6),SMALL_BUFF);
495 strncpy(pwent.pw_shell, dbretdata(dbproc,7),SMALL_BUFF);
496 more = 1;
497 vlimits_setflags(&pwent,domain);
498 return(&pwent);
499 }
500 more = 0;
501 dbcancel(dbproc);
502 return(NULL);
503 }
504
vauth_munch_domain(char * domain)505 char *vauth_munch_domain( char *domain )
506 {
507 int i;
508 static char tmpbuf[50];
509
510 if ( domain == NULL || domain[0] == 0 ) return(domain);
511
512 for(i=0;domain[i]!=0;++i){
513 tmpbuf[i] = domain[i];
514 if ( domain[i] == '.' || domain[i] == '-' ) {
515 tmpbuf[i] = SYBASE_DOT_CHAR;
516 }
517 }
518 tmpbuf[i] = 0;
519 return(tmpbuf);
520 }
521
vauth_setpw(struct vqpasswd * inpw,char * domain)522 int vauth_setpw( struct vqpasswd *inpw, char *domain )
523 {
524 return(vauth_setpw_size( inpw, domain, SITE_SIZE));
525 }
526
vauth_setpw_size(struct vqpasswd * inpw,char * domain,int site_size)527 int vauth_setpw_size( struct vqpasswd *inpw, char *domain, int site_size)
528 {
529 char *tmpstr;
530 uid_t myuid;
531 uid_t uid;
532 gid_t gid;
533
534 myuid = geteuid();
535 if ( myuid != VPOPMAIL && myuid != 0 ) return(VA_BAD_UID);
536
537 vauth_open();
538 vset_default_domain( domain );
539
540 if ( site_size == LARGE_SITE ) {
541 tmpstr = vauth_munch_domain( domain );
542 qnprintf( SqlBuf, sizeof(SqlBuf), LARGE_SETPW,
543 tmpstr,
544 inpw->pw_passwd,
545 inpw->pw_uid,
546 inpw->pw_gid,
547 inpw->pw_gecos,
548 inpw->pw_dir,
549 inpw->pw_shell,
550 inpw->pw_name );
551 } else {
552 qnprintf( SqlBuf, sizeof(SqlBuf), SMALL_SETPW,
553 SYBASE_DEFAULT_TABLE,
554 inpw->pw_passwd,
555 inpw->pw_uid,
556 inpw->pw_gid,
557 inpw->pw_gecos,
558 inpw->pw_dir,
559 inpw->pw_shell,
560 inpw->pw_name,
561 domain);
562 }
563
564 dbcmd(dbproc, SqlBuf);
565 if ( dbsqlexec(dbproc) == FAIL || dbresults(dbproc)== FAIL ) {
566 fprintf(stderr, "sybase query\n");
567 return(-1);
568 }
569 dbcancel(dbproc);
570
571 #ifdef SQWEBMAIL_PASS
572 tmpstr = vget_assign(domain, NULL, 0, &uid, &gid );
573 vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid);
574 #endif
575
576 #ifdef ONCHANGE_SCRIPT
577 if( allow_onchange ) {
578 /* tell other programs that data has changed */
579 snprintf ( onchange_buf, MAX_BUFF, "%s@%s", inpw->pw_name, domain );
580 call_onchange ( "mod_user" );
581 }
582 #endif
583
584 return(0);
585 }
586
vclear_open_smtp(time_t clear_minutes,time_t mytime)587 void vclear_open_smtp(time_t clear_minutes, time_t mytime)
588 {
589 /*
590 time_t delete_time;
591 int err;
592
593 if ( (err=vauth_open()) != 0 ) exit(0);
594 delete_time = mytime - clear_minutes;
595
596 snprintf( SqlBuf, sizeof(SqlBuf), "delete from relay where timestamp <= %d",
597 (int)delete_time);
598 if (mysql_query(&mysql,SqlBuf)) {
599 vcreate_relay_table();
600 return;
601 }
602 */
603 }
604
vmkpasswd(char * domain)605 int vmkpasswd( char *domain )
606 {
607 return(0);
608 }
609
vclose()610 void vclose()
611 {
612 if ( is_open == 1 ) {
613 is_open = 0;
614 dbclose(proc);
615 }
616 }
617
618 #ifdef IP_ALIAS_DOMAINS
vget_ip_map(char * ip,char * domain,int domain_size)619 int vget_ip_map( char *ip, char *domain, int domain_size)
620 {
621 if ( ip == NULL || strlen(ip) <= 0 ) return(0);
622 return(0);
623 }
624
vadd_ip_map(char * ip,char * domain)625 int vadd_ip_map( char *ip, char *domain)
626 {
627 return(0);
628 }
629
vdel_ip_map(char * ip,char * domain)630 int vdel_ip_map( char *ip, char *domain)
631 {
632 return(0);
633 }
634
635 int vshow_ip_map( int first, char *ip, char *domain);
636 {
637 return(0);
638 }
639 #endif
640
vauth_crypt(char * user,char * domain,char * clear_pass,struct vqpasswd * vpw)641 int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw)
642 {
643 if ( vpw == NULL ) return(-1);
644
645 return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd));
646 }
647