+/*
+Copyright (c) 2013 Eugene Crosser
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product documentation
+ would be appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+*/
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
+#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
* string.
*/
-static char *template = "~/.pam_cr/auth";
+static const char *template = "~/.pam_cr/auth";
-void authfile_template(char *str)
+void authfile_template(const char *str)
{
template = str;
}
static int path_size(const char *tokenid, const char *userid)
{
const char *usub;
- char *p, *q;
+ const char *p, *q;
struct passwd *pw;
if ((p = strchr(template, '~')) != strrchr(template, '~')) return 0;
} else {
usub = userid;
}
- return strlen(template) + p?strlen(usub):0 + q?strlen(tokenid):0 + 1;
+ return strlen(template)+(p?strlen(usub):0)+(q?strlen(tokenid):0)+1;
}
static void
make_path(char * const path, const char *tokenid, const char *userid)
{
const char *usub;
- char *p, *q;
+ const char *p;
+ char *q;
struct passwd *pw;
path[0] = '\0';
struct _auth_obj ret = {0};
mode_t oldmask;
FILE *fp = NULL;
- char *fn;
+ char *fn, *nfn;
int fnl;
+ struct stat st = {0};
char *buf = NULL;
struct {
const char *tokenid;
}
fn = alloca(fnl);
make_path(fn, tokenid, userid);
+ nfn = alloca(fnl+32);
+ snprintf(nfn, fnl+32, "%s.%d.%ld", fn, (int)getpid(), (long)time(NULL));
fp = fopen(fn, "r");
if (fp) {
- struct stat st;
- int fd = fileno(fp);
-
- if (fstat(fd, &st)) st.st_size = 2047;
+ if (fstat(fileno(fp), &st)) st.st_size = 2047;
if (st.st_size > 2047) st.st_size = 2047;
buf = alloca(st.st_size + 1);
if (!fgets(buf, st.st_size + 1, fp)) {
}
oldmask = umask(077);
- if ((fp = fopen(fn, "w"))) {
+ if ((fp = fopen(nfn, "w"))) {
int i;
if (fprintf(fp, "%s:%s:%s:", tokenid?tokenid:w.tokenid,
ret.err = strerror(errno);
}
fprintf(fp, "\n");
+ if (st.st_uid || st.st_gid) {
+ (void)fchown(fileno(fp), st.st_uid, st.st_gid);
+ }
if (fclose(fp) < 0) {
ret.err = strerror(errno);
}
ret.err = strerror(errno);
}
(void)umask(oldmask);
+ if (ret.err) {
+ unlink(nfn); /* may not exist but no matter */
+ } else if (rename(nfn, fn)) {
+ ret.err = strerror(errno);
+ }
if (!ret.err) {
- int bufsize = (w.userid?strlen(w.userid)+1:0) + ao.paylsize;
+ int bufsize = (w.userid?strlen(w.userid)+1:0) + ao.paylsize + 1;
if (bufsize) {
if ((ret.buffer = malloc(bufsize)) == NULL) {
ret.err = "authfile malloc failed";
}
if (ao.payload) {
memcpy(p, ao.payload, ao.paylsize);
+ p[ao.paylsize] = '\0';
ret.payload = p;
- ret.paylsize = ao.paylsize;
+ ret.paylsize = ao.paylsize+1;
}
}
}