17 * Template string may contain zero or one '~' and zero or one '?'.
18 * '~' at the beginning of the template string is substituted with
19 * the home directory of the userid. In any other position it is
20 * substituted with the userid itself. '?' is substituted with the
21 * tokenid. There is no way to make the resulting path contain '~'
22 * or '?'. If there is more than one '~' or '?', or if the '~' is
23 * at the beginning but userid does not resolve via getpwnam, or
24 * the character to substitute is present but the argument is NULL,
25 * NULL is returned. Otherwise, malloc()'ed area containg the path
29 static char *template = "~/.pam_cr/auth";
31 void authfile_template(char *str)
36 static char *make_path(const char *tokenid, const char *userid)
43 if ((p = strchr(template, '~')) != strrchr(template, '~')) return NULL;
44 if ((q = strchr(template, '?')) != strrchr(template, '?')) return NULL;
45 if (p && !userid) return NULL;
46 if (q && !tokenid) return NULL;
48 pw = getpwnam(userid);
54 path = malloc(strlen(template) + p?strlen(usub):0 +
55 q?strlen(tokenid):0 + 1);
56 if (!path) return NULL;
58 for (p = template; *p; p++) switch (*p) {
75 struct _auth_obj authfile(const char *tokenid,
76 const char *userid, const char *password,
77 void (*update_nonce)(char *nonce, const int nonsize),
78 const unsigned char *secret, const int secsize,
79 const unsigned char *payload, const int paylsize,
80 struct _auth_chunk (*fetch_key)(const unsigned char *chal,
83 struct _auth_obj ret = {0};
87 const char *wtokenid = NULL, *wuserid = NULL, *wnonce = NULL;
88 const char *hablob = NULL;
89 unsigned char *ablob = NULL;
95 if ((fn = make_path(tokenid, userid)) == NULL) {
96 ret.err = "authfile path impossible to build";
105 if (fstat(fd, &st)) st.st_size = 2047;
106 if (st.st_size > 2047) st.st_size = 2047;
107 buf = alloca(st.st_size + 1);
108 if (fgets(buf, st.st_size + 1, fp)) {
111 p = &buf[strlen(buf) - 1];
112 while (*p == '\n' || *p == '\r') *p-- = '\0';
113 wtokenid = strtok(buf, ":");
114 wuserid = strtok(NULL, ":");
115 wnonce = strtok(NULL, ":");
116 hablob = strtok(NULL, ":");
118 ret.err = strerror(errno);
122 if (ret.err) return ret;
125 int hlen = strlen(hablob);
126 if (hlen % 32 != 0) {
127 ret.err = "error: auth string has wrong length";
129 strspn(hablob, "0123456789abcdefABCDEF")) {
130 ret.err = "error: auth string not hexadecimal";
135 ablob = alloca(blobsize);
136 for (i = 0; i < blobsize; i++)
137 sscanf(&hablob[i*2], "%2hhx", &ablob[i]);
140 if (ret.err) return ret;
142 nonsize = wnonce ? strlen(wnonce)*2 : 32;
143 if (nonsize < 32) nonsize = 32;
144 newnonce = alloca(nonsize);
145 if (wnonce) strcpy(newnonce, wnonce);
146 else memset(newnonce, 0, nonsize);
147 update_nonce(newnonce, nonsize);
149 ao = authobj(userid?userid:wuserid, password,
150 wnonce, newnonce, secret, secsize,
151 payload, paylsize, ablob, blobsize,
156 if (ao.data) memset(ao.data, 0, ao.datasize);
157 if (ao.payload) memset(ao.payload, 0, ao.paylsize);
158 if (ao.buffer) free(ao.buffer);
162 if ((fp = fopen(fn, "w"))) {
165 if (fprintf(fp, "%s:%s:%s:", tokenid?tokenid:wtokenid,
166 userid?userid:wuserid, newnonce) < 0) {
167 ret.err = strerror(errno);
168 } else for (i = 0; i < ao.datasize; i++)
169 if (fprintf(fp, "%02x", ao.data[i]) < 0) {
170 ret.err = strerror(errno);
173 if (fclose(fp) < 0) {
174 ret.err = strerror(errno);
177 ret.err = strerror(errno);
181 int bufsize = (wuserid?strlen(wuserid)+1:0) + ao.paylsize;
183 if ((ret.buffer = malloc(bufsize)) == NULL) {
184 ret.err = "authfile malloc failed";
186 unsigned char *p = ret.buffer;
188 strcpy((char*)p, wuserid);
190 ret.datasize = strlen(wuserid)+1;
191 p += strlen(wuserid)+1;
194 memcpy(p, ao.payload, ao.paylsize);
196 ret.paylsize = ao.paylsize;
202 if (ao.data) memset(ao.data, 0, ao.datasize);
203 if (ao.payload) memset(ao.payload, 0, ao.paylsize);
204 if (ao.buffer) free(ao.buffer);