1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/* pop3front-auth.c -- POP3 authentication front-end
* Copyright (C) 2008 Bruce Guenter <bruce@untroubled.org> or FutureQuest, Inc.
* Development of this program was sponsored by FutureQuest, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* 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
*
* Contact information:
* FutureQuest Inc.
* PO BOX 623127
* Oviedo FL 32762-3127 USA
* http://www.FutureQuest.net/
* ossi@FutureQuest.net
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cvm/v2client.h>
#include <bglibs/iobuf.h>
#include <bglibs/striter.h>
#include <bglibs/str.h>
#include <cvm/sasl.h>
#include "pop3.h"
const char program[] = "pop3front-auth";
const int authenticating = 1;
static const char* cvm;
static char** nextcmd;
static const char* domain;
static str user;
static unsigned user_count;
static unsigned user_max;
static unsigned auth_count;
static unsigned auth_max;
static struct sasl_auth saslauth = { .prefix = "+ " };
static void do_exec(void)
{
if (!cvm_setugid() || !cvm_setenv())
respond(err_internal);
else {
alarm(0);
execvp(nextcmd[0], nextcmd);
respond("-ERR Could not execute second stage");
}
_exit(1);
}
static void cmd_auth_none(void)
{
static str auth_resp;
striter i;
switch (sasl_auth_caps(&auth_resp)) {
case 0:
respond(ok);
break;
case 1:
if (auth_resp.len <= 5) {
respond(err_internal);
return;
}
respond(ok);
str_lcut(&auth_resp, 5);
str_strip(&auth_resp);
striter_loop(&i, &auth_resp, ' ') {
obuf_write(&outbuf, i.startptr, i.len);
obuf_puts(&outbuf, CRLF);
}
break;
default:
respond(err_internal);
return;
}
respond(".");
}
static void cmd_auth(const str* s)
{
int i;
if ((i = sasl_auth1(&saslauth, s)) == 0)
do_exec();
obuf_write(&outbuf, "-ERR ", 5);
respond(sasl_auth_msg(&i));
++auth_count;
if (auth_max > 0 && auth_count >= auth_max)
exit(0);
}
static void cmd_user(const str* s)
{
++user_count;
if (user_max > 0 && user_count > user_max) {
respond("-ERR Too many USER commands issued");
exit(0);
}
if (!str_copy(&user, s))
respond(err_internal);
else
respond(ok);
}
static void cmd_pass(const str* s)
{
if (user.len == 0)
respond("-ERR Send USER first");
else {
int cr;
if ((cr = cvm_authenticate_password(cvm, user.s, domain, s->s, 1)) == 0)
do_exec();
str_truncate(&user, 0);
if (cr == CVME_PERMFAIL)
respond("-ERR Authentication failed");
else
respond(err_internal);
++auth_count;
if (auth_max > 0 && auth_count >= auth_max)
exit(0);
}
}
static void cmd_quit(void)
{
respond(ok);
exit(0);
}
command commands[] = {
{ "CAPA", cmd_capa, 0, 0 },
{ "AUTH", cmd_auth_none, cmd_auth, 0 },
{ "PASS", 0, cmd_pass, "PASS XXXXXXXX" },
{ "QUIT", cmd_quit, 0, 0 },
{ "USER", 0, cmd_user, 0 },
{ 0, 0, 0, 0 }
};
int startup(int argc, char* argv[])
{
static const char usage[] = "usage: pop3front-auth cvm program [args...]\n";
const char* tmp;
if ((tmp = getenv("MAXUSERCMD")) != 0)
user_max = strtoul(tmp, 0, 10);
if ((tmp = getenv("MAXAUTHFAIL")) != 0)
auth_max = strtoul(tmp, 0, 10);
if ((domain = cvm_ucspi_domain()) == 0)
domain = "unknown";
if (argc < 3) {
obuf_putsflush(&errbuf, usage);
return 0;
}
cvm = argv[1];
nextcmd = argv+2;
if (!sasl_auth_init(&saslauth)) {
respond("-ERR Could not initialize SASL AUTH");
return 0;
}
return 1;
}
|