[courier-users] authsqlite

This is a discussion on [courier-users] authsqlite within the Courier-Imap forums, part of the Mail Servers and Related category; This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --===============1473658569== Content-Type: multipart/signed; micalg=pgp-sha1; protocol=&...


Go Back   Usenet Forums > Mail Servers and Related > Courier-Imap

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 04-23-2008
Fabiano Sidler
 
Posts: n/a
Default [courier-users] authsqlite

This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--===============1473658569==
Content-Type: multipart/signed; micalg=pgp-sha1;
protocol="application/pgp-signature";
boundary="------------enigA850BAB8FE598EA66D9461B0"

This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enigA850BAB8FE598EA66D9461B0
Content-Type: multipart/mixed; boundary="------------060002000708030204000906"

This is a multi-part message in MIME format.
--------------060002000708030204000906
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: quoted-printable

Hi folks!

I've written a backend for authlib to sqlite3. It's not complete yet, tho=
ugh,
there are still sever{e,al} security checks missing, which I'll fix after=
-
wards.
Now: what exactly needs to be done to integrate it into the source? Sorry=

for asking such a question, but I mainly develop in Python and have no cl=
ue
about the authlib source structure.

Greetings,
Fabiano

--------------060002000708030204000906
Content-Type: text/plain;
name="authsqlite.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline;
filename="authsqlite.c"

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sqlite3.h>
#include "auth.h"
#include "authstaticlist.h"

#if HAVE_CONFIG_H
#include "courier_auth_config.h"
#endif
#if HAVE_HMACLIB
#include "libhmac/hmac.h"
#include "cramlib.h"
#endif

typedef struct authinfo authinfo;
typedef int* (*callback)(authinfo*, void*);
typedef void (*enumcallback)
(const char*, uid_t, gid_t, const char*, const char*, void*);

static int auth_sqlite(
const char *service,
const char *authtype,
char *authdata,
callback *cb,
void *cbarg);
static int auth_sqlite_no_vrfy(
const char *user,
const char *service,
callback *cb,
void *cbarg);
static void auth_sqlite_exit(
void);
static int auth_sqlite_chgpwd(
const char *service,
const char *user,
const char *oldpwd,
const char *newpwd);
static void auth_sqlite_idle(
void);
static void auth_sqlite_enum(
enumcallback *cb,
void *cbarg);
static struct authstaticinfo authsqlite_info=3D{
"authsqlite",
auth_sqlite,
auth_sqlite_no_vrfy,
auth_sqlite_exit,
auth_sqlite_chgpwd,
auth_sqlite_idle,
auth_sqlite_enum,
};

static sqlite3 *db;
char *errmsg=3DNULL;
int rc;
char
*dbfilename,
*emailfld, *uidfld, *gidfld, *homefld, *maildirfld, *passwdfld,
*clearpwfld, *optionsfld, *fullnamefld, *quotafld,
*table, *pop3table, *imaptable, *smtptable,
*userfmt, *pop3userfmt, *imapuserfmt, *smtpuserfmt,
*usersfmt, *pop3usersfmt, *imapusersfmt, *smtpusersfmt,
*updatefmt, *pop3updatefmt, *imapupdatefmt, *smtpupdatefmt;

void err(char *fmt, ...)
{
va_list args;
va_start(args,fmt);
vprintf(fmt, args);
va_end(args);
}

static char* concat(
char *first,
char *next,
...)
{
va_list args1, args2;
int retlen=3D0;
char *p,*ret,*retend;
=09
retlen =3D strlen(first) + strlen(next);
va_start(args1, next);
va_copy(args2, args1);
while (p=3Dva_arg(args1, char*)) retlen +=3D strlen(p);
va_end(args1);
ret =3D (char*) malloc(sizeof(char)*retlen);
retend =3D ret;
while (p=3Dva_arg(args2, char*)) {
strcpy(retend,p);
retend-=3D1;
}
va_end(args2);
return ret;
}

static struct {
char *svc;
char *userfmt;
char *usersfmt;
char *updatefmt;
int userlen;
int userslen;
int updatelen;
} svc_stmt[] =3D {
{"NONE",0},
{"pop3",0},
{"imap",0},
{"smtp",0},
};

extern struct authstaticinfo *courier_authsqlite_init(
void)
{
char *tmp;
#define VAR(x,def) (tmp=3Dread_env(#x)) ? tmp : def
dbfilename =3D VAR(DBFILENAME,"/etc/courier/authsqlite.db");
emailfld =3D VAR(EMAIL,"email");
uidfld =3D VAR(UID,"uid");
gidfld =3D VAR(GID,"gid");
homefld =3D VAR(HOMEFLD,"home");
maildirfld =3D VAR(MAILDIR,"maildir");
passwdfld =3D VAR(PASSWD,"passwd");
clearpwfld =3D VAR(CLEARPW,"clearpw");
optionsfld =3D VAR(OPTIONS,"options");
fullnamefld =3D VAR(FULLNAME,"fullname");
quotafld =3D VAR(QUOTA,"quota");
table =3D VAR(TABLE,"users");
pop3table =3D VAR(POP3TABLE,table);
imaptable =3D VAR(IMAPTABLE,table);
smtptable =3D VAR(SMTPTABLE,table);
#undef VAR
userfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",homef=
ld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",table," where ",emailfld,"=3D%s", NU=
LL);
pop3userfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",h=
omefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",pop3table," where ",emailfld,"=3D%s"=
, NULL);
imapuserfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",h=
omefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",imaptable," where ",emailfld,"=3D%s"=
, NULL);
smtpuserfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",h=
omefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",smtptable," where ",emailfld,"=3D%s"=
, NULL);
usersfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",home=
fld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",table, NULL);
pop3usersfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",=
homefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",pop3table, NULL);
imapusersfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",=
homefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",imaptable, NULL);
smtpusersfmt =3D concat("select ",emailfld,", ",uidfld,", ",gidfld,", ",=
homefld,
", ",maildirfld,", ",passwdfld,", ",clearpwfld,", ",optionsfld,", ",
fullnamefld,", ",quotafld," from ",smtptable, NULL);
updatefmt =3D concat("update ",table, " set ", passwdfld,"=3D%s",
" where ",emailfld,"=3D%s", NULL);
pop3updatefmt =3D concat("update ",pop3table, " set ", passwdfld,"=3D%s"=
,
" where ",emailfld,"=3D%s", NULL);
imapupdatefmt =3D concat("update ",imaptable, " set ", passwdfld,"=3D%s"=
,
" where ",emailfld,"=3D%s", NULL);
smtpupdatefmt =3D concat("update ",smtptable, " set ", passwdfld,"=3D%s"=
,
" where ",emailfld,"=3D%s", NULL);
svc_stmt[0].userfmt =3D userfmt;
svc_stmt[0].usersfmt =3D usersfmt;
svc_stmt[0].updatefmt =3D updatefmt;
svc_stmt[0].userlen =3D strlen(userfmt);
svc_stmt[0].userslen =3D strlen(usersfmt);
svc_stmt[0].updatelen =3D strlen(updatefmt);
svc_stmt[1].userfmt =3D pop3userfmt;
svc_stmt[1].usersfmt =3D pop3usersfmt;
svc_stmt[1].updatefmt =3D pop3updatefmt;
svc_stmt[1].userlen =3D strlen(pop3userfmt);
svc_stmt[1].userslen =3D strlen(pop3usersfmt);
svc_stmt[1].updatelen =3D strlen(pop3updatefmt);
svc_stmt[2].userfmt =3D imapuserfmt;
svc_stmt[2].usersfmt =3D imapusersfmt;
svc_stmt[2].updatefmt =3D imapupdatefmt;
svc_stmt[2].userlen =3D strlen(imapuserfmt);
svc_stmt[2].userslen =3D strlen(imapusersfmt);
svc_stmt[2].updatelen =3D strlen(imapupdatefmt);
svc_stmt[3].userfmt =3D smtpuserfmt;
svc_stmt[3].usersfmt =3D smtpusersfmt;
svc_stmt[3].updatefmt =3D smtpupdatefmt;
svc_stmt[3].userlen =3D strlen(smtpuserfmt);
svc_stmt[3].userslen =3D strlen(smtpusersfmt);
svc_stmt[3].updatelen =3D strlen(smtpupdatefmt);
/* open db connection */
if (sqlite3_open(dbfilename, &db)) {
sqlite3_close(db);
return NULL;
}
return &authsqlite_info;
}

static int get_user(
char *user,
char *service,
char ***res,
int *r,
int *c,
char **e)
{
int i;
char *sql;
if (!strcmp(service, svc_stmt[1].svc)) i=3D1;
else if (!strcmp(service,svc_stmt[2].svc)) i=3D2;
else if (!strcmp(service,svc_stmt[3].svc)) i=3D3;
else {
*e =3D "invalid service";
return 1;
}
sql =3D (char*) malloc(svc_stmt[i].userlen+strlen(user));
if (sprintf(&sql,svc_stmt[i].userfmt,user)=3D=3D-1) {
*e =3D "sprintf failed!";
return 5;
}
if (sqlite3_get_table(db, sql, &res, &r, &c, NULL)!=3DSQLITE_OK) {
*e =3D "SQL statement failed";
sqlite3_free_table(&res);
return 2;
}
if (*r=3D=3D0) {
*e =3D "user not found";
sqlite3_free_table(&res);
return 3;
}
if (*r>1) {
*e =3D "ambiguous user name";
sqlite3_free_table(&res);
return 4;
}
return 0;
}

static int get_users(
char *service,
char ***res,
int *r,
int *c,
char **e)
{
int i;
if (!strcmp(service, svc_stmt[1].svc)) i=3D1;
else if (!strcmp(service,svc_stmt[2].svc)) i=3D2;
else if (!strcmp(service,svc_stmt[3].svc)) i=3D3;
else {
*e =3D "invalid service";
return 1;
}
if (sqlite3_get_table(db, svc_stmt[i].usersfmt, &res, &r, &c, NULL)
!=3DSQLITE_OK) {
*e =3D "SQL statement failed";
sqlite3_free_table(&res);
return 2;
}
return 0;
}

static int get_user_errhnd(
char *svc,
char **res,
int errval,
char *mesg)
{
if (errval=3D=3D1 || errval=3D=3D3) {
err("error getting user: %s", mesg);
errno=3DEINVAL;
return -1;
} else if (errval=3D=3D2 || errval=3D=3D4) {
err("error getting user: %s", mesg);
errno=3DEPERM;
return 1;
}
}

static int get_users_errhnd(
char *svc,
char **res,
int errval,
char *mesg)
{
err("error getting users: %s", mesg);
return errval;
}

static int auth_sqlite_common(
const char *user,
const char *pass,
const char *service,
callback *cb,
void *cbarg)
{
char **res;
int r,c,ret;
char *e;
authinfo info =3D {0};
if (!(ret=3Dget_user(user,service,&res,&r,&c,&e))) {
return get_user_errhnd(service,res,ret,e); }
info.sysusername =3D NULL;
info.address =3D res[1][0];
info.sysuserid =3D strtol(res[1][1], NULL, 0);
info.sysgroupid =3D strtol(res[1][2], NULL, 0);
info.homedir =3D res[1][3] ;
info.maildir =3D res[1][4];
info.passwd =3D res[1][5];
info.clearpasswd =3D res[1][6];
info.options =3D res[1][7];
info.fullname =3D res[1][8];
info.quota =3D res[1][9];
return (*cb)(&info, cbarg);
}

static int auth_sqlite(
const char *service,
const char *authtype,
char *authdata,
callback *cb,
void *cbarg)
{
if (strcmp(authtype, AUTHTYPE_LOGIN) =3D=3D 0) {
const char *user, *pass;
if ((user=3Dstrtok(authdata, "\n")) =3D=3D NULL ||
(pass=3Dstrtok(0, "\n")) =3D=3D NULL) {
errno=3DEPERM;
return (-1);
}
return auth_sqlite_common(user, pass, service, cb, cbarg);
}
#if HAVE_HMACLIB
struct cram_callback_info cci;
if (auth_get_cram(authtype, authdata, &cci)) return (-1);
cci.callback_func =3D cb;
cci.callback_arg =3D cbarg;
return auth_sqlite_common(cci.user, NULL, service, cb, (void*)&cci);
#else
return -1;
#endif
}

static int auth_sqlite_no_vrfy(
const char *user,
const char *service,
callback *cb,
void *cbarg)
{
return auth_sqlite_common(user, NULL, service, cb, cbarg);
}

static void auth_sqlite_exit(
void)
{
sqlite3_close(db);
}

static int auth_sqlite_chgpwd(
const char *service,
const char *user,
const char *oldpw,
const char *newpw)
{
/* TODO */
char **res;
int r,c,ret,i;
char *e;
if (!(ret=3Dget_user(user,service,&res,&r,&c,&e))) {
return get_user_errhnd(service,res,ret,e); }
if (res[1][5]) { // crypted pw
if (authcheckpassword(oldpw,res[1][5])) {
err("wrong password for user %s", user);
errno=3DEPERM;
return 1;
}
} else if (res[1][6]) { // clear pw
if (strcmp(oldpw,res[1][6])) {
err("wrong password for user %s", user);
errno=3DEPERM;
return 1;
}
} else {
err("clear pw and crypted pw unset");
errno=3DEPERM;
return 1;
}
char *newcryptpw =3D authcryptpasswd(newpw,res[1][5]);
char *sql;
if (!strcmp(service, svc_stmt[1].svc)) i=3D1;
else if (!strcmp(service,svc_stmt[2].svc)) i=3D2;
else if (!strcmp(service,svc_stmt[3].svc)) i=3D3;
else {
err("invalid service: %s",service);
errno=3DEPERM;
return 2;
}
sql =3D (char*) malloc(svc_stmt[i].updatelen+strlen(user));
if (sprintf(&sql,svc_stmt[i].updatefmt,user)=3D=3D-1) {
err("sprintf failed!");
errno=3DEPERM;
return 3;
}
if (sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=3DSQLITE_ OK) {
err("error updating passwd: %s", errmsg);
sqlite3_free(errmsg);
errno=3DEPERM;
return 1;
}
sqlite3_free_table(res);
/* passwd successfully changed */
return 0;
}

static void auth_sqlite_idle(
void)
{
return;
}

static void auth_sqlite_enum(
enumcallback *cb,
void *cbarg)
{
/* TODO */
char **res,*e,*svc=3DNULL;
int pop3used=3D0, imapused=3D0, smtpused=3D0, r,c,ret,i;
if (!strcmp(usersfmt,pop3usersfmt)) pop3used=3D1;
if (!strcmp(usersfmt,imapusersfmt)) imapused=3D1;
if (!strcmp(usersfmt,smtpusersfmt)) smtpused=3D1;
if (pop3used) {
if (!(ret=3Dget_users("pop3",&res,&r,&c,&e))) {
get_users_errhnd("pop3",res,ret,e);
return;
}
for (i=3D1;i<=3Dr;i++) {
(*cb)(res[i][0],
strtol(res[i][1], NULL, 0), strtol(res[i][2], NULL, 0),
res[i][3], res[i][4], cbarg); }
sqlite3_free_table(res);
}
if (imapused) {
if (!(ret=3Dget_users("imap",&res,&r,&c,&e))) {
get_users_errhnd("imap",res,ret,e);
return;
}
for (i=3D1;i<=3Dr;i++) {
(*cb)(res[i][0],
strtol(res[i][1], NULL, 0), strtol(res[i][2], NULL, 0),
res[i][3], res[i][4], cbarg); }
sqlite3_free_table(res);
}
if (smtpused) {
if (!(ret=3Dget_users("smtp",&res,&r,&c,&e))) {
get_users_errhnd("smtp",res,ret,e);
return;
}
for (i=3D1;i<=3Dr;i++) {
(*cb)(res[i][0],
strtol(res[i][1], NULL, 0), strtol(res[i][2], NULL, 0),
res[i][3], res[i][4], cbarg); }
sqlite3_free_table(res);
}
if (!pop3used) svc=3D"pop3";
else if (!imapused) svc=3D"imap";
else if (!smtpused) svc=3D"smtp";
if (!svc) {
if (!(ret=3Dget_users(svc,&res,&r,&c,&e))) {
get_users_errhnd(svc,res,ret,e);
return;
}
for (i=3D1;i<=3Dr;i++) {
(*cb)(res[i][0],
strtol(res[i][1], NULL, 0), strtol(res[i][2], NULL, 0),
res[i][3], res[i][4], cbarg); }
sqlite3_free_table(res);
}
sqlite3_free_table(res);
(*cb)(NULL, 0, 0, NULL, NULL, cbarg);
return;
}

--------------060002000708030204000906--

--------------enigA850BAB8FE598EA66D9461B0
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgPaM0ACgkQrxVzXk9cDowieQCeKQRlfvkNhX guJ/G1gufiUVjS
HSEAn31GIkWilDhWroH5oGO/dZuoXWCe
=yj0T
-----END PGP SIGNATURE-----

--------------enigA850BAB8FE598EA66D9461B0--


--===============1473658569==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757...un.com/javaone
--===============1473658569==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
courier-users mailing list
courier-users@lists.sourceforge.net
Unsubscribe: https://lists.sourceforge.net/lists/.../courier-users

--===============1473658569==--

Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 04:49 PM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0