Added LOGIN auth method (for MS exchange). You also get support for the destination of net!$smtp which I submitted before but was dropped. Sorry but I still use it. Notes: Tue Jan 4 11:02:12 EST 2005 rsc My problem with this the last time was that it did ndbipinfo itself, which is always going to cause problems. What if cs is running on a different machine and you don't even have access to the network databases it is using? I realize this is uncommon but Dave did work hard to make remote network stacks work. It turns out that /net/cs already does what you want, almost. It has a magic query !ipinfo sys=you smtp which will return smtp=your.smtp.server The only problem is what to say as sys=you. Really you want the IP address that cs is using. So I changed cs to use ip=its.ip.address when you omit the attr=val. So now !ipinfo smtp will return smtp=your.smtp.server which is what you're looking for. You'll need to look at the network address being dialed for any net prefixes. That is, if the address being dialed is /net.alt/tcp!$auth!smtp then you need to ask /net.alt/cs not /net/cs. If you change the patch to use this mechanism to figure out how to translate $smtp then I'll gladly apply it. Russ Reference: /n/sources/patch/sorry/smtp-auth-login Date: Tue Jan 4 17:06:29 CET 2005 Reviewed-by: rsc --- /sys/src/cmd/upas/smtp/smtp.c Tue Jan 4 17:06:30 2005 +++ /sys/src/cmd/upas/smtp/smtp.c Tue Jan 4 17:06:30 2005 @@ -3,11 +3,12 @@ #include #include #include +#include #include static char* connect(char*); static char* dotls(char*); -static char* doauth(void); +static char* doauth(char*); char* hello(char*, int); char* mailfrom(char*); char* rcptto(char*); @@ -238,11 +239,9 @@ } rv = data(from, &bfile); -if(debug) fprint(2, "data rv %s\n", rv); if(rv != 0) goto error; quit(0); -if(debug) fprint(2, "rcvrs %d ok %d\n", rcvrs, ok); if(rcvrs == ok) exits(0); @@ -267,10 +266,8 @@ ping ? "ping" : "delivery", addr, s_to_c(reply)); fprint(2, "%s connect to %s:\n%s\n", thedate(), addr, s_to_c(reply)); -if(debug) fprint(2, "errors %s\n", rv); if(!filter) quit(rv); -if(debug) fprint(2, "exits %s\n", rv); exits(rv); } @@ -367,42 +364,96 @@ */ Binit(&bin, fd, OREAD); fd = dup(fd, -1); -if(debug)fprint(2, "bout fd = %d\n", fd); Binit(&bout, fd, OWRITE); syslog(0, "smtp", "started TLS to %q", ddomain); return(hello(me, 1)); } +char * +meta(char *m) +{ + Ndb *db; + char *r, *s = m +1; + Ndbtuple *t; + + if ((db = ndbopen(nil)) == nil) + return m; + + if ((t = ndbipinfo(db, "sys", alt_sysname_read(), &s, 1)) == nil){ + ndbclose(db); + return m; + } + r = strdup(t->val); + ndbfree(t); + ndbclose(db); + return r; +} + static char * -doauth(void) +doauth(char *methods) { - char *buf, *base64; + char *sys, *buf, *base64; UserPasswd *p; int n; + sys = ddomain; + if (*sys == '$') + sys = meta(sys); + if(user != nil) p = auth_getuserpasswd(nil, - "proto=pass service=smtp server=%q user=%q", ddomain, user); + "proto=pass service=smtp server=%q user=%q", sys, user); else p = auth_getuserpasswd(nil, - "proto=pass service=smtp server=%q", ddomain); + "proto=pass service=smtp server=%q", sys); if (p == nil) return Giveup; - n = strlen(p->user) + strlen(p->passwd) + 3; - buf = malloc(n); - base64 = malloc(2 * n); - if (buf == nil || base64 == nil) { + + if (strstr(methods, "LOGIN")){ + dBprint("AUTH LOGIN\r\n"); + if (getreply() != 3) + return Retry; + + n = strlen(p->user); + base64 = malloc(2*n); + if (base64 == nil) + return Retry; /* Out of memory */ + enc64(base64, 2*n, (uchar *)p->user, n); + dBprint("%s\r\n", base64); + if (getreply() != 3) + return Retry; + + n = strlen(p->passwd); + base64 = malloc(2*n); + if (base64 == nil) + return Retry; /* Out of memory */ + enc64(base64, 2*n, (uchar *)p->passwd, n); + dBprint("%s\r\n", base64); + if (getreply() != 2) + return Retry; + + free(base64); + } + else + if (strstr(methods, "PLAIN")){ + n = strlen(p->user) + strlen(p->passwd) + 3; + buf = malloc(n); + base64 = malloc(2 * n); + if (buf == nil || base64 == nil) { + free(buf); + return Retry; /* Out of memory */ + } + snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd); + enc64(base64, 2 * n, (uchar *)buf, n - 1); free(buf); - return Retry; /* Out of memory */ + dBprint("AUTH PLAIN %s\r\n", base64); + free(base64); + if (getreply() != 2) + return Retry; } - snprint(buf, n, "%c%s%c%s", 0, p->user, 0, p->passwd); - enc64(base64, 2 * n, (uchar *)buf, n - 1); - free(buf); - dBprint("AUTH PLAIN %s\r\n", base64); - free(base64); - if (getreply() != 2) - return Retry; + else + return "No supported AUTH method; return(0); } @@ -411,7 +462,7 @@ { int ehlo; String *r; - char *s, *t; + char *ret, *s, *t; if (!encrypted) switch(getreply()){ @@ -458,10 +509,10 @@ } if(tryauth && (encrypted || insecure) && (strncmp(s, "250 AUTH", strlen("250 AUTH")) == 0 || - strncmp(s, "250-AUTH", strlen("250 AUTH")) == 0) && - strstr(s, "PLAIN") != nil){ + strncmp(s, "250-AUTH", strlen("250 AUTH")) == 0)){ + ret = doauth(s + strlen("250 AUTH ")); s_free(r); - return(doauth()); + return ret; } } s_free(r);