void setup_env(char *user, struct credentials *c) { /* set up the environment for the execution of the subprogram */ if (!env_put2("USER", user)) auth_error(ERRNO); /* only courier-imap needs this but we set it anyway */ if (!env_put2("AUTHENTICATED", user)) auth_error(ERRNO); if (c->home.s != 0 && c->home.len > 0) if (!env_put2("HOME", c->home.s)) auth_error(ERRNO); if (c->maildir.s != 0 && c->maildir.len > 0) { if (!env_put2("MAILDIR", c->maildir.s)) auth_error(ERRNO); } else { if (!env_unset("MAILDIR")) auth_error(ERRNO); } logit(32, "environment successfully set: " "USER %s, HOME %s, MAILDIR %s\n", user, c->home.s != 0 && c->home.len > 0? c->home.s:"unset, forwarding", c->maildir.s != 0 && c->maildir.len > 0? c->maildir.s:"unset, using aliasempty"); }
static void execute(const char *fn,const char *def) /* Load and execute a qmail command file. */ { stralloc file = {0,0,0}; int code; if (def != 0) env_put2("DEFAULT",def); else env_unset("DEFAULT"); if (slurp(fn,&file,256) != 1) strerr_die6sys(111,FATAL,ERR_READ_INPUT,basedir.s,"/",fn,": "); code = execute_file(fn,&file); substdio_puts(subfderr,"did 0+"); substdio_put(subfderr,strnum,fmt_ulong(strnum,did_forward)); substdio_puts(subfderr,"+"); substdio_put(subfderr,strnum,fmt_ulong(strnum,did_program)); substdio_putsflush(subfderr,"\n"); _exit(code); }
int check_ldap(stralloc *login, stralloc *authdata, struct credentials *c, int fast) { static stralloc ld = {0}; qldap *q; char *filter; int r, status, pwok, needforward; unsigned long count, size, max; const char *attrs[] = { LDAP_UID, /* the first 10 attrs are default */ LDAP_QMAILUID, LDAP_QMAILGID, LDAP_ISACTIVE, LDAP_MAILHOST, LDAP_MAILSTORE, LDAP_HOMEDIR, LDAP_QUOTA_SIZE, LDAP_QUOTA_COUNT, LDAP_MAXMSIZE, LDAP_PASSWD, 0}; /* passwd is extra */ /* TODO more debug output is needed */ needforward = 0; q = qldap_new(); if (q == 0) return ERRNO; r = qldap_open(q); if (r != OK) goto fail; r = qldap_bind(q, 0, 0); if (r != OK) goto fail; if (fast) { /* just comapre passwords and account status */ attrs[0] = LDAP_ISACTIVE; if (qldap_need_rebind() == 0) { attrs[1] = LDAP_PASSWD; attrs[2] = 0; } else attrs[1] = 0; } else { if (qldap_need_rebind() != 0) attrs[10] = 0; } filter = filter_uid(login->s); if (filter == 0) { r = ERRNO; goto fail; } r = qldap_lookup(q, filter, attrs); if (r != OK) goto fail; r = qldap_get_status(q, &status); if (r != OK) goto fail; if (status == STATUS_BOUNCE || status == STATUS_NOACCESS || status == STATUS_DELETE) { qldap_free(q); return ACC_DISABLED; } if (!fast) { #ifdef QLDAP_CLUSTER r = qldap_get_attr(q, LDAP_MAILHOST, &c->forwarder, SINGLE_VALUE); if (r != OK && r != NOSUCH) goto fail; if (r == OK && cluster(c->forwarder.s) == 1) { /* hostname is different, so I reconnect */ logit(8, "check_ldap: forwarding session to %s\n", c->forwarder.s); needforward = 1; } #endif r = qldap_get_uid(q, &c->uid); if (r != OK) goto fail; r = qldap_get_gid(q, &c->gid); if (r != OK) goto fail; r = qldap_get_mailstore(q, &c->home, &c->maildir); if (r != OK) goto fail; if (!stralloc_0(&c->home) || !stralloc_0(&c->maildir)) return ERRNO; size = count = max = 0; r = qldap_get_quota(q, &size, &count, &max); if (r != OK) goto fail; if (max != 0) { num[fmt_ulong(num, max)] = 0; if (!env_put2("DATASIZE", num)) auth_error(ERRNO); } if (size != 0 || count != 0) { if (!stralloc_copys(&ld, "")) auth_error(ERRNO); if (size != 0) { if (!stralloc_catb(&ld, num, fmt_ulong(num, size))) auth_error(ERRNO); if (!stralloc_append(&ld, "S")) auth_error(ERRNO); } if (count != 0) { if (size != 0) if (!stralloc_append(&ld, ",")) auth_error(ERRNO); if (!stralloc_catb(&ld, num, fmt_ulong(num, count))) auth_error(ERRNO); if (!stralloc_append(&ld, "C")) auth_error(ERRNO); } if (!stralloc_0(&ld)) auth_error(ERRNO); if (!env_put2(ENV_QUOTA, ld.s )) auth_error(ERRNO); } } if (qldap_need_rebind() == 0) { r = qldap_get_attr(q, LDAP_PASSWD, &ld, SINGLE_VALUE); if (r != OK) goto fail; pwok = cmp_passwd(authdata->s, ld.s); } else { r = qldap_get_dn(q, &ld); if (r != OK) goto fail; r = qldap_rebind(q, ld.s, authdata->s); switch (r) { case OK: pwok = OK; break; case LDAP_BIND_AUTH: pwok = BADPASS; break; default: pwok = r; break; } } logit(32, "check_ldap: password compare was %s\n", pwok == OK?"successful":"not successful"); qldap_free(q); if (pwok == OK && needforward == 1) return FORWARD; return pwok; fail: qldap_free(q); return r; }
void main(int argc,char **argv) { char *sender; char *def; char *local; char *action; int flaginheader; int flagcomment; int flaggoodfield; int flagdone; int fd, fdlock; int match; const char *err; char encin = '\0'; unsigned int start,confnum; unsigned int pos,i; int child; int opt; char *cp,*cpnext,*cpfirst,*cplast,*cpafter; (void) umask(022); sig_pipeignore(); when = now(); if (!stralloc_copys(&sendopt,"-")) die_nomem(); opt = getconfopt(argc,argv,options,1,&dir); sender = get_sender(); if (!sender) strerr_die2x(100,FATAL,MSG(ERR_NOSENDER)); local = env_get("LOCAL"); if (!local) strerr_die2x(100,FATAL,MSG(ERR_NOLOCAL)); def = env_get("DEFAULT"); if (!def) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT)); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (!sender[str_chr(sender,'@')]) strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS)); if (str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); /* local should be >= def, but who knows ... */ cp = local + str_len(local) - str_len(def) - 2; if (cp < local) die_badformat(); action = local + byte_rchr(local,cp - local,'-'); if (action == cp) die_badformat(); action++; if (!action[0]) die_badformat(); if (!str_start(action,ACTION_ACCEPT) && !str_start(action,ACTION_REJECT)) die_badformat(); start = str_chr(action,'-'); if (!action[start]) die_badformat(); confnum = 1 + start + str_chr(action + start + 1,'.'); if (!action[confnum]) die_badformat(); confnum += 1 + str_chr(action + confnum + 1,'.'); if (!action[confnum]) die_badformat(); if (!stralloc_copyb(&fnbase,action+start+1,confnum-start-1)) die_nomem(); if (!stralloc_0(&fnbase)) die_nomem(); cookie(hash,key.s,key.len,fnbase.s,"","a"); if (byte_diff(hash,COOKIE,action+confnum+1)) die_badformat(); fdlock = lockfile("mod/lock"); switch(checkfile(fnbase.s)) { case 0: strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT)); case -1: /* only error if new request != action taken */ if (str_start(action,ACTION_ACCEPT)) strerr_die2x(0,INFO,MSG(ERR_MOD_ACCEPTED)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_ACCEPTED)); case -2: if (str_start(action,ACTION_REJECT)) strerr_die2x(0,INFO,MSG(ERR_MOD_REJECTED)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_REJECTED)); default: break; } /* Here, we have an existing filename in fnbase with the complete path */ /* from the current dir in fnmsg. */ if (str_start(action,ACTION_REJECT)) { if (qmail_open(&qq, (stralloc *) 0) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); /* Build recipient from msg return-path */ fd = open_read(fnmsg.s); if (fd == -1) { if (errno != error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT)); } substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (getln(&sstext,&line,&match,'\n') == -1 || !match) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); maketo(); /* extract SENDER from return-path */ /* Build message */ hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST)); if (listid.len > 0) hdr_add2("List-ID: ",listid.s,listid.len); hdr_datemsgid(when); hdr_from("-owner"); if (replyto) hdr_add2s("Reply-To: ",replyto); hdr_add2s("To: ",to.s); hdr_subject(MSG(SUB_RETURNED_POST)); if (flagmime) { hdr_mime(CTYPE_MULTIPART); hdr_boundary(0); hdr_ctype(CTYPE_TEXT); hdr_transferenc(); } copy(&qq,"text/top",flagcd); copy(&qq,"text/mod-reject",flagcd); flagcomment = 0; flaginheader = 1; if (!stralloc_copys(&text,"")) die_nomem(); if (!stralloc_ready(&text,1024)) die_nomem(); for (;;) { /* copy moderator's rejection comment */ if (getln(subfdin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (flaginheader) { if (case_startb(line.s,line.len,"Content-Transfer-Encoding:")) { pos = 26; while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos; if (case_startb(line.s+pos,line.len-pos,"base64")) encin = 'B'; else if (case_startb(line.s+pos,line.len-pos,"quoted-printable")) encin = 'Q'; } if (line.len == 1) flaginheader = 0; } else if (!stralloc_cat(&text,&line)) die_nomem(); } /* got body */ if (encin) { if (encin == 'B') decodeB(text.s,text.len,&line); else decodeQ(text.s,text.len,&line); if (!stralloc_copy(&text,&line)) die_nomem(); } cp = text.s; cpafter = text.s + text.len; if (!stralloc_copys(&line,"\n>>>>> -------------------- >>>>>\n")) die_nomem(); flaggoodfield = 0; flagdone = 0; while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) { i = byte_chr(cp,cpnext-cp,'%'); if (i <= 5 && cpnext-cp-i >= 3) { /* max 5 "quote characters" and space for %%% */ if (cp[i+1] == '%' && cp[i+2] == '%') { if (!flaggoodfield) { /* Start tag */ if (!stralloc_copyb("ed,cp,i)) die_nomem(); /* quote chars*/ flaggoodfield = 1; cp = cpnext + 1; cpfirst = cp; continue; } else { /* end tag */ if (flagdone) /* 0 no comment lines, 1 comment line */ flagdone = 2; /* 2 at least 1 comment line & end tag */ break; } } } if (flaggoodfield) { cplast = cpnext - 1; if (*cplast == '\r') /* CRLF -> '\n' for base64 encoding */ *cplast = '\n'; else ++cplast; /* NUL is now ok, so the test for it was removed */ flagdone = 1; i = cplast - cp + 1; if (quoted.len && quoted.len <= i && !str_diffn(cp,quoted.s,quoted.len)) { /* quote chars */ if (!stralloc_catb(&line,cp+quoted.len,i-quoted.len)) die_nomem(); } else if (!stralloc_catb(&line,cp,i)) die_nomem(); /* no quote chars */ } cp = cpnext + 1; } if (flagdone == 2) { if (!stralloc_cats(&line,"<<<<< -------------------- <<<<<\n")) die_nomem(); code_qput(line.s,line.len); } if (flagcd == 'B') { encodeB("",0,&line,2); qmail_put(&qq,line.s,line.len); } if (flagmime) { hdr_boundary(0); hdr_ctype(CTYPE_MESSAGE); } qmail_puts(&qq,"\n"); if (seek_begin(fd) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s)); substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (qmail_copy(&qq,&sstext,-1) != 0) strerr_die2sys(111,FATAL,MSG1(ERR_READ,fnmsg.s)); close(fd); if (flagmime) hdr_boundary(1); if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-return-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); if (!stralloc_0(&line)) die_nomem(); qmail_from(&qq,line.s); if (to.len) qmail_to(&qq,to.s); if (!stralloc_copys(&fnnew,"mod/rejected/")) die_nomem(); if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); /* this is strictly to track what happended to a message to give informative */ /* messages to the 2nd-nth moderator that acts on the same message. Since */ /* this isn't vital we ignore errors. Also, it is no big ideal if unlinking */ /* the old file fails. In the worst case it gets acted on again. If we issue */ /* a temp error the reject will be redone, which is slightly worse. */ if (*(err = qmail_close(&qq)) == '\0') { fd = open_trunc(fnnew.s); if (fd != -1) close(fd); unlink(fnmsg.s); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die2x(0,"ezmlm-moderate: info: qp ",strnum); } else strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); } else if (str_start(action,ACTION_ACCEPT)) { fd = open_read(fnmsg.s); if (fd == -1) { if (errno !=error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s)); else /* shouldn't happen since we've got lock */ strerr_die3x(100,FATAL,fnmsg.s,MSG(ERR_MOD_TIMEOUT)); } substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); /* read "Return-Path:" line */ if (getln(&sstext,&line,&match,'\n') == -1 || !match) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); maketo(); /* extract SENDER to "to" */ env_put2("SENDER",to.s); /* set SENDER */ if (seek_begin(fd) == -1) /* rewind, since we read an entire buffer */ strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s)); if ((child = wrap_fork()) == 0) { close(0); dup(fd); /* make fnmsg.s stdin */ if (argc > opt + 1) wrap_execvp((const char **)argv + opt); else if (argc > opt) wrap_execsh(argv[opt]); else wrap_execbin("/ezmlm-send", &sendopt, dir); } /* parent */ close(fd); wrap_exitcode(child); if (!stralloc_copys(&fnnew,"mod/accepted/")) die_nomem(); if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); /* ignore errors */ fd = open_trunc(fnnew.s); if (fd != -1) close(fd); unlink(fnmsg.s); _exit(0); } }
int main(int argc, char **argv) { enum { unset, uid, mail, filter } mode = unset; qldap *q, *qpw; struct passwd *pw; char *passwd = 0, *value = 0; char *bindpw = 0, *binddn = 0; char *f, *s; int opt, r, done, status, id; unsigned int j, slen; unsigned long size, count, maxsize; const char *attrs[] = { LDAP_MAIL, LDAP_MAILALTERNATE, LDAP_UID, LDAP_QMAILUID, LDAP_QMAILGID, LDAP_ISACTIVE, LDAP_MAILHOST, LDAP_MAILSTORE, LDAP_HOMEDIR, LDAP_QUOTA_SIZE, LDAP_QUOTA_COUNT, LDAP_FORWARDS, LDAP_PROGRAM, LDAP_MODE, LDAP_REPLYTEXT, LDAP_DOTMODE, LDAP_MAXMSIZE, LDAP_OBJECTCLASS, #if 0 LDAP_GROUPCONFIRM, LDAP_GROUPMEMONLY, LDAP_GROUPCONFRIMTEXT, LDAP_GROUPMODERATTEXT, LDAP_GROUPMODERATDN, LDAP_GROUPMODERAT822, LDAP_GROUPMEMBERDN, LDAP_GROUPMEMBER822, LDAP_GROUPMEMBERFILTER, #endif LDAP_PASSWD, 0}; while ((opt = getopt(argc, argv, "d:D:u:m:p:f:w:")) != opteof) switch (opt) { case 'd': if (env_put2("LOGLEVEL", optarg) == 0) strerr_die2sys(1, FATAL, "setting loglevel: "); break; case 'D': binddn = optarg; break; case 'u': if (value != 0) usage(); value = optarg; mode = uid; break; case 'm': if (value != 0) usage(); value = optarg; mode = mail; break; case 'f': if (value != 0) usage(); value = optarg; mode = filter; break; case 'p': if (geteuid() != 0) strerr_die2x(1, FATAL, "only the superuser may comapre passwords"); passwd = optarg; break; case 'w': bindpw = optarg; break; default: usage(); } if (argc != optind) usage(); if (bindpw && !binddn) usage(); log_init(STDERR, -1, 0); if (read_controls(ctrls) != 0) strerr_die2sys(111, FATAL, "unable to read controls: "); q = qldap_new(); if (q == 0) strerr_die2sys(111, FATAL, "qldap_new failed: "); qpw = qldap_new(); if (qpw == 0) strerr_die2sys(111, FATAL, "qldap_new failed: "); r = qldap_open(q); if (r != OK) fail(q, "qldap_open", r); r = qldap_open(qpw); if (r != OK) fail(qpw, "qldap_open", r); r = qldap_bind(q, binddn, bindpw); if (r != OK) fail(q, "qldap_bind", r); if (passwd == 0 || mode != uid || qldap_need_rebind() != 0) attrs[sizeof(attrs)/4 - 2] = 0; /* password */ done = 0; f = 0; do { switch (mode) { case mail: f = filter_mail(value, &done); if (value == 0) strerr_die2sys(1, FATAL, "building filter: "); break; case uid: f = filter_uid(value); done = 1; if (value == 0) strerr_die2sys(1, FATAL, "building filter: "); break; case filter: f = value; break; default: usage(); } output(subfdout, "Searching ldap for: %s\nunder dn: %s\n", f, qldap_basedn()); r = qldap_filter(q, f, attrs, qldap_basedn(), SCOPE_SUBTREE); if (r != OK) fail(q, "qldap_filter", r); r = qldap_count(q); switch (r) { case -1: fail(q, "qldap_count", FAILED); case 0: output(subfdout, "No entries found.\n"); qldap_free(q); /* TODO hook for local lookups. */ return 0; case 1: output(subfdout, "Found %i entry:\n", r); break; default: output(subfdout, "Found %i entries:\n", r); if (mode == uid || mode == uid) { output(subfdout, "Uh-oh: multiple entries found but " "should be unique!\n"); passwd = 0; } break; } output(subfdout, "\n"); } while (r == 0 && !done); r = qldap_first(q); if (r != OK) fail(q, "qldap_first", r);; do { r = qldap_get_dn(q, &dn); if (r != OK) fail(q, "qldap_get_dn", r); output(subfdout, "dn: %s\n" "-------------------------------------------------------\n", dn.s); r = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_OBJECTCLASS ")", r); unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n",LDAP_OBJECTCLASS ,s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } r = qldap_get_attr(q, LDAP_MAIL, &foo, SINGLE_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_MAIL ")", r); output(subfdout, "%s: %s\n", LDAP_MAIL, foo.s); r = qldap_get_attr(q, LDAP_MAILALTERNATE, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MAILALTERNATE ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_MAILALTERNATE, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_user(q, &foo); if (r != OK && r != NOSUCH) fail(q, "qldap_get_user", r); if (r == OK) output(subfdout, "%s: %s\n", LDAP_UID, foo.s); else output(subfdout, "%s: undefined " "(forward only account required)\n", LDAP_UID); r = qldap_get_status(q, &status); if (r != OK) fail(q, "qldap_get_status", r); switch (status) { case STATUS_BOUNCE: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_BOUNCE); break; case STATUS_NOACCESS: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_NOACCESS); break; case STATUS_OK: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_ACTIVE); break; case STATUS_UNDEF: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, "undefined -> active"); break; default: strerr_warn2(WARN, "qldap_get_status returned unknown status", 0); } r = qldap_get_attr(q, LDAP_MAILHOST, &foo, SINGLE_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MAILHOST ")", r); if (r == OK) { output(subfdout, "%s: %s\n", LDAP_MAILHOST, foo.s); /* * TODO we could check if we are in cluster mode and * if we would redirect to a differnet host */ } else output(subfdout, "%s: undefined\n", LDAP_MAILHOST); /* get the path of the maildir or mbox */ r = qldap_get_mailstore(q, &foo, &bar); switch (r) { case OK: output(subfdout, "homeDirectory: %s\n", foo.s); if (bar.len > 0) output(subfdout, "aliasEmpty: %s\n", bar.s); else output(subfdout, "aliasEmpty: using default\n"); break; case NEEDED: output(subfdout, "forward only delivery via alias user\n"); pw = getpwnam(auto_usera); if (!pw) strerr_die4x(100, FATAL, "Aiiieeeee, now alias user '", auto_usera, "'found in /etc/passwd."); output(subfdout, "alias user: %s\n", pw->pw_name); output(subfdout, "alias user uid: %i\n", pw->pw_uid); output(subfdout, "alias user gid: %i\n", pw->pw_gid); output(subfdout, "alias user home: %s\n", pw->pw_dir); output(subfdout, "alias user aliasempty: %s\n", ALIASDEVNULL); /* get the forwarding addresses */ r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_FORWARDS ") for forward only user", r); unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } goto next; default: fail(q, "qldap_get_mailstore", r); } r = qldap_get_dotmode(q, &foo); if (r != OK) fail(q, "qldap_get_dotmode", r); output(subfdout, "%s: %s\n", LDAP_DOTMODE, foo.s); r = qldap_get_uid(q, &id); if (r != OK) fail(q, "qldap_get_uid", r); output(subfdout, "%s: %i\n", LDAP_QMAILUID, id); r = qldap_get_gid(q, &id); if (r != OK) fail(q, "qldap_get_gid", r); output(subfdout, "%s: %i\n", LDAP_QMAILGID, id); r = qldap_get_quota(q, &size, &count, &maxsize); if (r != OK) fail(q, "qldap_get_quota", r); output(subfdout, "%s: %u%s\n", LDAP_QUOTA_SIZE, size, size==0?" (unlimited)":""); output(subfdout, "%s: %u%s\n", LDAP_QUOTA_COUNT, count, count==0?" (unlimited)":""); output(subfdout, "%s: %u%s\n", LDAP_MAXMSIZE, maxsize, maxsize==0?" (unlimited)":""); r = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MODE ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { if (case_diffs(MODE_FORWARD, s) && case_diffs(MODE_REPLY, s) && case_diffs(MODE_NOLOCAL, s) && case_diffs(MODE_NOMBOX, s) && case_diffs(MODE_NOFORWARD, s) && case_diffs(MODE_NOPROG, s) && case_diffs(MODE_LOCAL, s) && case_diffs(MODE_FORWARD, s) && case_diffs(MODE_PROG, s) && case_diffs(MODE_NOREPLY, s)) strerr_warn4(WARN, "undefined mail delivery mode: ", s," (ignored).", 0); else if (!case_diffs(MODE_FORWARD, s)) strerr_warn4(WARN, "mail delivery mode: ", s," should not be used " "(used internally).", 0); output(subfdout, "%s: %s\n", LDAP_MODE, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_FORWARDS ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_PROGRAM ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_PROGRAM, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_REPLYTEXT ")", r); if (r == OK) output(subfdout, "%s:\n=== begin ===\n%s\n" "=== end ===\n", LDAP_REPLYTEXT, foo.s); else output(subfdout, "%s: undefined\n", LDAP_REPLYTEXT); if (mode == uid && passwd != 0) { if (qldap_need_rebind() == 0) { r = qldap_get_attr(q, LDAP_PASSWD, &foo, SINGLE_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_PASSWD ")", r); r = cmp_passwd(passwd, foo.s); } else { r = qldap_rebind(qpw, dn.s, passwd); switch (r) { case OK: r = OK; break; case LDAP_BIND_AUTH: r = BADPASS; break; default: break; } } output(subfdout, "\nPASSWORD COMPARE was %s.\n", r == OK?"successful":"NOT successful"); if (r != OK) output(subfdout, "\terror was: %s\n", qldap_err_str(r)); } next: r = qldap_next(q); output(subfdout, "\n\n"); } while (r == OK); if (r != NOSUCH) fail(q, "qldap_next", r); qldap_free(q); return 0; }