X-Git-Url: https://git.hcoop.net/hcoop/debian/courier-authlib.git/blobdiff_plain/ac40fd9eb9d1980c90dc009d526a23ead1ec0f76..4bc1ba6f5ecc4e62b1cd99eec25a9a0f510a3d70:/authdaemon.c?ds=sidebyside diff --git a/authdaemon.c b/authdaemon.c index 4773b58..7f24431 100644 --- a/authdaemon.c +++ b/authdaemon.c @@ -1,10 +1,10 @@ /* -** Copyright 2000-2008 Double Precision, Inc. See COPYING for +** Copyright 2000-2015 Double Precision, Inc. See COPYING for ** distribution information. */ #include "auth.h" -#include "authstaticlist.h" +#include "courierauthstaticlist.h" #include "courierauthsasl.h" #include "authwait.h" #include "courierauthdebug.h" @@ -17,8 +17,10 @@ #include #include #include "numlib/numlib.h" - -static const char rcsid[]="$Id: authdaemon.c,v 1.18 2008/06/29 16:39:24 mrsam Exp $"; +#include +#include +#include +#include extern int authdaemondo(const char *authreq, int (*func)(struct authinfo *, void *), void *arg); @@ -112,3 +114,182 @@ int auth_callback_default(struct authinfo *ainfo) return 0; } + +static void do_copy(const char *from, + const char *to, + struct stat *stat_buf, + uid_t uid, + gid_t gid) +{ + FILE *fp=fopen(from, "r"); + FILE *fp2; + int c; + + if (!fp) + { + fprintf(stderr, "WARN: %s: %s!!\n", from, strerror(errno)); + return; + } + + fp2=fopen(to, "w"); + + if (!fp2) + { + fprintf(stderr, "WARN: %s: %s!!\n", to, strerror(errno)); + fclose(fp); + return; + } + + while ((c=getc(fp)) != EOF) + putc(c, fp2); + fclose(fp); + fclose(fp2); + + if (chmod(to, stat_buf->st_mode & ~S_IFMT) || + chown(to, uid, gid) < 0) + { + fprintf(stderr, "WARN: %s: %s!!\n", to, strerror(errno)); + } +} + +static void do_symlink(const char *from, + const char *to, + uid_t uid, + gid_t gid) +{ + char buf[1024]; + ssize_t l=readlink(from, buf, sizeof(buf)-1); + + if (l < 0) + { + fprintf(stderr, "WARN: %s: %s!!\n", from, strerror(errno)); + return; + } + buf[l]=0; + + if (symlink(buf, to) < 0 || lchown(to, uid, gid) < 0) + { + fprintf(stderr, "WARN: %s: %s!!\n", from, strerror(errno)); + return; + } +} + +static int do_mkhomedir(const char *skeldir, + const char *homedir, + uid_t uid, + gid_t gid) +{ + struct stat stat_buf; + DIR *d; + struct dirent *de; + + mkdir(homedir, 0); + + if (stat(skeldir, &stat_buf) < 0 || + chmod(homedir, stat_buf.st_mode & ~S_IFMT) || + chown(homedir, uid, gid) < 0) + { + fprintf(stderr, "WARN: %s: %s!!\n", skeldir, strerror(errno)); + return 0; + } + + if ((d=opendir(skeldir)) != NULL) + { + while ((de=readdir(d)) != NULL) + { + char *fskeldir, *fhomedir; + + if (strcmp(de->d_name, ".") == 0) + continue; + if (strcmp(de->d_name, "..") == 0) + continue; + + fskeldir=malloc(strlen(skeldir)+2+strlen(de->d_name)); + fhomedir=malloc(strlen(homedir)+2+strlen(de->d_name)); + + if (fskeldir && fhomedir) + { + strcat(strcat(strcpy(fskeldir, skeldir), "/"), + de->d_name); + strcat(strcat(strcpy(fhomedir, homedir), "/"), + de->d_name); + + if (lstat(fskeldir, &stat_buf) == 0) + { + if (S_ISDIR(stat_buf.st_mode)) + { + do_mkhomedir(fskeldir, fhomedir, + uid, gid); + } + else if (S_ISLNK(stat_buf.st_mode)) + { + do_symlink(fskeldir, fhomedir, + uid, gid); + } + else if (S_ISREG(stat_buf.st_mode)) + { + do_copy(fskeldir, fhomedir, + &stat_buf, + uid, gid); + } + } + } + + if (fskeldir) + free(fskeldir); + if (fhomedir) + free(fhomedir); + } + closedir(d); + } + return 0; +} + +static int mkhomedir(struct authinfo *ainfo, + const char *skel) +{ + if (ainfo->sysusername) + { + struct passwd *pw=getpwnam(ainfo->sysusername); + return do_mkhomedir(skel, ainfo->homedir, + pw->pw_uid, + pw->pw_gid); + } + + return do_mkhomedir(skel, ainfo->homedir, + *ainfo->sysuserid, ainfo->sysgroupid); +} + +int auth_mkhomedir(struct authinfo *ainfo) +{ + struct stat stat_buf; + + const char *p=getenv("AUTH_MKHOMEDIR_SKEL"); + + if (p && *p && ainfo->address && + (ainfo->sysusername || ainfo->sysuserid) && + ainfo->homedir && stat(ainfo->homedir, &stat_buf) < 0 && + errno == ENOENT && stat(p, &stat_buf) == 0) + { + int rc; + mode_t old_umask=umask(0777); + + rc=mkhomedir(ainfo, p); + + umask(old_umask); + + if (rc) + return rc; + } + return 0; +} + +int auth_callback_default_autocreate(struct authinfo *ainfo) +{ + int rc=auth_mkhomedir(ainfo); + + if (rc) + return rc; + + return auth_callback_default(ainfo); +}