2 ** Copyright 2000-2015 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courierauthstaticlist.h"
8 #include "courierauthsasl.h"
10 #include "courierauthdebug.h"
18 #include <sys/select.h>
19 #include "numlib/numlib.h"
22 #include <sys/types.h>
25 extern int authdaemondo(const char *authreq
,
26 int (*func
)(struct authinfo
*, void *), void *arg
);
28 extern void auth_daemon_enumerate( void(*cb_func
)(const char *name
,
38 int auth_generic(const char *service
,
41 int (*callback_func
)(struct authinfo
*, void *),
44 char tbuf
[NUMBUFSIZE
];
45 size_t l
=strlen(service
)+strlen(authtype
)+strlen(authdata
)+2;
46 char *n
=libmail_str_size_t(l
, tbuf
);
47 char *buf
=malloc(strlen(n
)+l
+20);
50 courier_authdebug_login_init();
55 strcat(strcat(strcpy(buf
, "AUTH "), n
), "\n");
56 strcat(strcat(buf
, service
), "\n");
57 strcat(strcat(buf
, authtype
), "\n");
58 strcat(buf
, authdata
);
60 rc
=strcmp(authtype
, "EXTERNAL") == 0
61 ? auth_getuserinfo(service
, authdata
, callback_func
,
63 : authdaemondo(buf
, callback_func
, callback_arg
);
66 if (courier_authdebug_login_level
)
70 /* short delay to try and allow authdaemond's courierlogger
71 to finish writing; otherwise items can appear out of order */
74 select(0, 0, 0, 0, &t
);
80 int auth_callback_default(struct authinfo
*ainfo
)
82 if (ainfo
->address
== NULL
)
84 fprintf(stderr
, "WARN: No address!!\n");
88 if (ainfo
->sysusername
)
89 libmail_changeusername(ainfo
->sysusername
,
91 else if (ainfo
->sysuserid
)
92 libmail_changeuidgid(*ainfo
->sysuserid
,
96 fprintf(stderr
, "WARN: %s: No UID/GID!!\n", ainfo
->address
);
103 fprintf(stderr
, "WARN: %s: No homedir!!\n", ainfo
->address
);
107 if (chdir(ainfo
->homedir
))
109 fprintf(stderr
, "WARN: %s: chdir(%s) failed!!\n",
110 ainfo
->address
, ainfo
->homedir
);
111 perror("WARN: error");
118 static void do_copy(const char *from
,
120 struct stat
*stat_buf
,
124 FILE *fp
=fopen(from
, "r");
130 fprintf(stderr
, "WARN: %s: %s!!\n", from
, strerror(errno
));
138 fprintf(stderr
, "WARN: %s: %s!!\n", to
, strerror(errno
));
143 while ((c
=getc(fp
)) != EOF
)
148 if (chmod(to
, stat_buf
->st_mode
& ~S_IFMT
) ||
149 chown(to
, uid
, gid
) < 0)
151 fprintf(stderr
, "WARN: %s: %s!!\n", to
, strerror(errno
));
155 static void do_symlink(const char *from
,
161 ssize_t l
=readlink(from
, buf
, sizeof(buf
)-1);
165 fprintf(stderr
, "WARN: %s: %s!!\n", from
, strerror(errno
));
170 if (symlink(buf
, to
) < 0 || lchown(to
, uid
, gid
) < 0)
172 fprintf(stderr
, "WARN: %s: %s!!\n", from
, strerror(errno
));
177 static int do_mkhomedir(const char *skeldir
,
182 struct stat stat_buf
;
188 if (stat(skeldir
, &stat_buf
) < 0 ||
189 chmod(homedir
, stat_buf
.st_mode
& ~S_IFMT
) ||
190 chown(homedir
, uid
, gid
) < 0)
192 fprintf(stderr
, "WARN: %s: %s!!\n", skeldir
, strerror(errno
));
196 if ((d
=opendir(skeldir
)) != NULL
)
198 while ((de
=readdir(d
)) != NULL
)
200 char *fskeldir
, *fhomedir
;
202 if (strcmp(de
->d_name
, ".") == 0)
204 if (strcmp(de
->d_name
, "..") == 0)
207 fskeldir
=malloc(strlen(skeldir
)+2+strlen(de
->d_name
));
208 fhomedir
=malloc(strlen(homedir
)+2+strlen(de
->d_name
));
210 if (fskeldir
&& fhomedir
)
212 strcat(strcat(strcpy(fskeldir
, skeldir
), "/"),
214 strcat(strcat(strcpy(fhomedir
, homedir
), "/"),
217 if (lstat(fskeldir
, &stat_buf
) == 0)
219 if (S_ISDIR(stat_buf
.st_mode
))
221 do_mkhomedir(fskeldir
, fhomedir
,
224 else if (S_ISLNK(stat_buf
.st_mode
))
226 do_symlink(fskeldir
, fhomedir
,
229 else if (S_ISREG(stat_buf
.st_mode
))
231 do_copy(fskeldir
, fhomedir
,
248 static int mkhomedir(struct authinfo
*ainfo
,
251 if (ainfo
->sysusername
)
253 struct passwd
*pw
=getpwnam(ainfo
->sysusername
);
254 return do_mkhomedir(skel
, ainfo
->homedir
,
259 return do_mkhomedir(skel
, ainfo
->homedir
,
260 *ainfo
->sysuserid
, ainfo
->sysgroupid
);
263 int auth_mkhomedir(struct authinfo
*ainfo
)
265 struct stat stat_buf
;
267 const char *p
=getenv("AUTH_MKHOMEDIR_SKEL");
269 if (p
&& *p
&& ainfo
->address
&&
270 (ainfo
->sysusername
|| ainfo
->sysuserid
) &&
271 ainfo
->homedir
&& stat(ainfo
->homedir
, &stat_buf
) < 0 &&
272 errno
== ENOENT
&& stat(p
, &stat_buf
) == 0)
275 mode_t old_umask
=umask(0777);
277 rc
=mkhomedir(ainfo
, p
);
287 int auth_callback_default_autocreate(struct authinfo
*ainfo
)
289 int rc
=auth_mkhomedir(ainfo
);
294 return auth_callback_default(ainfo
);