Commit 25319ee8 25319ee8fe3c2bf91ffa2523269cc5fb3e79796d by Sam Roberts

wicket: a ticket file now can contain multiple urls, when looking for

a ticket, the first one which contains authentication information for
the incomplete url is returned. wildcards are ok, so you can do:
  pop://sam:pass@pop.uniserve.com
  *://sroberts:gnuless@mail.certicom.com
  imap://;AUTH=anon@*
Actually, the last doesn't work, but it SHOULD. Another day.
1 parent 5df8b25a
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 30
31 #include <mailutils/mutil.h> 31 #include <mailutils/mutil.h>
32 #include <auth0.h> 32 #include <auth0.h>
33 #include <url0.h>
33 34
34 struct myticket_data 35 struct myticket_data
35 { 36 {
...@@ -38,12 +39,11 @@ struct myticket_data ...@@ -38,12 +39,11 @@ struct myticket_data
38 char *filename; 39 char *filename;
39 }; 40 };
40 41
41 static char * stripwhite __P ((char *));
42 static int myticket_create __P ((ticket_t *, const char *, const char *, const char *)); 42 static int myticket_create __P ((ticket_t *, const char *, const char *, const char *));
43 static void myticket_destroy __P ((ticket_t)); 43 static void myticket_destroy __P ((ticket_t));
44 static int myticket_pop __P ((ticket_t, url_t, const char *, char **)); 44 static int myticket_pop __P ((ticket_t, url_t, const char *, char **));
45 static char * get_pass __P ((url_t, const char *, const char *)); 45 static int get_pass __P ((url_t, const char *, const char *, char**));
46 static char * get_user __P ((url_t, const char *)); 46 static int get_user __P ((url_t, const char *, char **));
47 47
48 int 48 int
49 wicket_create (wicket_t *pwicket, const char *filename) 49 wicket_create (wicket_t *pwicket, const char *filename)
...@@ -164,8 +164,6 @@ myticket_create (ticket_t *pticket, const char *user, const char *pass, const ch ...@@ -164,8 +164,6 @@ myticket_create (ticket_t *pticket, const char *user, const char *pass, const ch
164 status = ENOMEM; 164 status = ENOMEM;
165 return status; 165 return status;
166 } 166 }
167 if (!pass)
168 mdata->pass = get_pass (NULL, user, filename);
169 } 167 }
170 168
171 if (pass) 169 if (pass)
...@@ -186,13 +184,41 @@ static int ...@@ -186,13 +184,41 @@ static int
186 myticket_pop (ticket_t ticket, url_t url, const char *challenge, char **parg) 184 myticket_pop (ticket_t ticket, url_t url, const char *challenge, char **parg)
187 { 185 {
188 struct myticket_data *mdata = NULL; 186 struct myticket_data *mdata = NULL;
187 int e = 0;
188
189 ticket_get_data (ticket, (void **)&mdata); 189 ticket_get_data (ticket, (void **)&mdata);
190 if (challenge && (strstr (challenge, "ass") != NULL 190 if (challenge &&
191 || strstr (challenge, "ASS") != NULL)) 191 (
192 *parg = (mdata->pass) ? strdup (mdata->pass) : get_pass (url, mdata->user, mdata->filename); 192 strstr (challenge, "ass") != NULL ||
193 strstr (challenge, "ASS") != NULL
194 )
195 )
196 {
197 if(mdata->pass)
198 {
199 *parg = strdup(mdata->pass);
200 if(!*parg)
201 e = ENOMEM;
202 }
193 else 203 else
194 *parg = (mdata->user) ? strdup (mdata->user) : get_user (url, mdata->filename); 204 {
195 return 0; 205 e = get_pass (url, mdata->user, mdata->filename, parg);
206 }
207 }
208 else
209 {
210 if(mdata->user)
211 {
212 *parg = strdup(mdata->user);
213 if(!*parg)
214 e = ENOMEM;
215 }
216 else
217 {
218 e = get_user (url, mdata->filename, parg);
219 }
220 }
221 return e;
196 } 222 }
197 223
198 static void 224 static void
...@@ -212,132 +238,213 @@ myticket_destroy (ticket_t ticket) ...@@ -212,132 +238,213 @@ myticket_destroy (ticket_t ticket)
212 } 238 }
213 } 239 }
214 240
215 /* Strip whitespace from the start and end of STRING. Return a pointer 241 static int
216 into STRING. */ 242 get_ticket (url_t url, const char *user, const char *filename, url_t * ticket)
217 static char *
218 stripwhite (char *string)
219 { 243 {
220 register char *s, *t; 244 int err = 0;
245 FILE *fp = NULL;
246 size_t buflen = 128;
247 char *buf = NULL;
221 248
222 for (s = string; isspace (*s); s++)
223 ;
224 249
225 if (*s == 0) 250 if (!filename || !url)
226 return (s); 251 return EINVAL;
227 252
228 t = s + strlen (s) - 1; 253 fp = fopen (filename, "r");
229 while (t > s && isspace (*t))
230 t--;
231 *++t = '\0';
232 254
233 return s; 255 if (!fp)
234 } 256 return errno;
235 257
236 static char * 258 buf = malloc (buflen);
237 get_user (url_t url, const char *filename)
238 {
239 struct passwd *pw;
240 char *u = (char *)"";
241 if (url)
242 {
243 size_t n = 0;
244 url_get_user (url, NULL, 0, &n);
245 u = calloc (1, n + 1);
246 url_get_user (url, u, n + 1, NULL);
247 return u;
248 }
249 else if (filename)
250 {
251 /* do something. */
252 }
253 pw = getpwuid (getuid ());
254 if (pw)
255 u = pw->pw_name;
256 return strdup (u);
257 }
258
259 static char *
260 get_pass (url_t url, const char *u, const char *filename)
261 {
262 char *user = NULL;
263 char *pass = NULL;
264 259
265 if (u) 260 if (!buf)
266 user = strdup (u);
267 else if (url)
268 { 261 {
269 size_t n = 0; 262 fclose (fp);
270 url_get_user (url, NULL, 0, &n); 263 return ENOMEM;
271 user = calloc (1, n + 1);
272 url_get_user (url, user, n + 1, NULL);
273 } 264 }
274 else
275 user = get_user (NULL, filename);
276 265
277 if (filename && user) 266 while (!feof (fp) && !ferror (fp))
278 {
279 FILE *fp;
280 fp = fopen (filename, "r");
281 if (fp)
282 {
283 char *buf;
284 size_t buflen;
285
286 buflen = 128;
287 buf = malloc (buflen);
288 if (buf)
289 { 267 {
290 char *ptr = buf; 268 char *ptr = buf;
269 int len = 0;
270 url_t u = NULL;
271
272 /* fgets:
273 1) return true, read some data
274 1a) read a newline, so break
275 1b) didn't read newline, so realloc & continue
276 2) returned NULL, so no more data
277 */
291 while (fgets (ptr, buflen, fp) != NULL) 278 while (fgets (ptr, buflen, fp) != NULL)
292 { 279 {
293 size_t len = strlen (buf); 280 char *tmp = NULL;
294 char *sep; 281 len = strlen (buf);
295 /* Check if a complete line. */ 282 /* Check if a complete line. */
296 if (len && buf[len - 1] != '\n') 283 if (len && buf[len - 1] == '\n')
297 {
298 char *tmp = realloc (buf, 2*buflen);
299 if (tmp == NULL)
300 break; 284 break;
285
286 buflen *= 2;
287 tmp = realloc (buf, buflen);
288 if (tmp == NULL)
289 {
290 free (buf);
291 fclose (fp);
292 return ENOMEM;
293 }
301 buf = tmp; 294 buf = tmp;
302 ptr = buf + len; 295 ptr = buf + len;
303 continue;
304 } 296 }
305 297
298 len = strlen (buf);
299
300 /* Truncate a trailing newline. */
301 if (len && buf[len - 1] == '\n')
302 buf[len - 1] = 0;
303
304 /* Skip leading spaces. */
306 ptr = buf; 305 ptr = buf;
306 while (isspace (*ptr))
307 ptr++;
307 308
308 /* Comments. */ 309 /* Skip comments. */
309 if (*ptr == '#') 310 if (*ptr == '#')
310 continue; 311 continue;
311 312
312 /* Skip leading spaces. */ 313 /* Skip empty lines. */
313 while (isspace (*ptr)) 314 if ((len = strlen (ptr)) == 0)
315 continue;
316
317 if ((err = url_create (&u, ptr)) != 0)
314 { 318 {
315 ptr++; 319 free (buf);
316 len--; 320 fclose (fp);
321 return err;
322 }
323 if ((err = url_parse (u)) != 0)
324 {
325 /* TODO: send output to the debug stream */
326 /*
327 printf ("url_parse %s failed: [%d] %s\n", str, err, strerror (err));
328 */
329 url_destroy (&u);
330 continue;
317 } 331 }
318 332
319 /* user:passwd. Separator maybe ": \t" */ 333
320 if (len && ((sep = memchr (ptr, ':', len)) != NULL 334 if (!url_is_ticket (u, url))
321 || (sep = memchr (ptr, ' ', len)) != NULL
322 || (sep = memchr (ptr, '\t', len)) != NULL))
323 { 335 {
324 *sep++ = '\0'; 336 url_destroy (&u);
325 ptr = stripwhite (ptr); 337 continue;
326 if (strcmp (ptr, user) == 0) 338 }
339 /* Also needs to be for name, if we required. */
340 if (user)
327 { 341 {
328 pass = strdup (stripwhite (sep)); 342 if (u->name && strcmp (u->name, "*") != 0
343 && strcmp (user, u->name) != 0)
344 {
345 url_destroy (&u);
346 continue;
347 }
348 }
349
350 /* Looks like a match! */
351 *ticket = u;
352 u = NULL;
329 break; 353 break;
330 } 354 }
355
356 fclose (fp);
357 free (buf);
358
359 return 0;
360 }
361
362 static int
363 get_user (url_t url, const char *filename, char **user)
364 {
365 char *u = 0;
366
367 if (url)
368 {
369 size_t n = 0;
370 url_get_user (url, NULL, 0, &n);
371
372 if (n)
373 {
374 u = calloc (1, n + 1);
375 url_get_user (url, u, n + 1, NULL);
376 }
377 }
378 if (!u && filename)
379 {
380 url_t ticket = 0;
381 int e = get_ticket (url, NULL, filename, &ticket);
382 if (e)
383 return e;
384
385 if (ticket)
386 {
387 size_t n = 0;
388 url_get_user (ticket, NULL, 0, &n);
389
390 if (n)
391 {
392 u = calloc (1, n + 1);
393 url_get_user (ticket, u, n + 1, NULL);
394 }
395 url_destroy (&ticket);
331 } 396 }
332 ptr = buf;
333 } 397 }
398 else
399 {
400 struct passwd *pw = getpwuid (getuid ());
401 if (pw && pw->pw_name)
402 {
403 u = strdup (pw->pw_name);
404 if (!u)
405 return ENOMEM;
334 } 406 }
407 }
408 *user = u;
409 return 0;
410 }
335 411
336 if (buf) 412 static int
337 free (buf); 413 get_pass (url_t url, const char *user, const char *filename, char **pass)
338 fclose (fp); 414 {
415 char *u = 0;
416
417 if (url)
418 {
419 size_t n = 0;
420 url_get_passwd (url, NULL, 0, &n);
421
422 if (n)
423 {
424 u = calloc (1, n + 1);
425 url_get_passwd (url, u, n + 1, NULL);
339 } 426 }
340 } 427 }
341 free (user); 428 if (!u && filename)
342 return pass; 429 {
430 url_t ticket = 0;
431 int e = get_ticket (url, user, filename, &ticket);
432 if (e)
433 return e;
434
435 if (ticket)
436 {
437 size_t n = 0;
438 url_get_passwd (ticket, NULL, 0, &n);
439
440 if (n)
441 {
442 u = calloc (1, n + 1);
443 url_get_passwd (ticket, u, n + 1, NULL);
444 }
445 url_destroy (&ticket);
446 }
447 }
448 *pass = u;
449 return 0;
343 } 450 }
......