auth.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:7k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** auth.c
  3. **
  4. ** Copyright (c) 1994-1997 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <string.h>
  20. #include <syslog.h>
  21. #include <alloca.h>
  22. #include "phttpd.h"
  23. /* Allocate a new authinfo structure */
  24. struct authinfo *auth_new(const char *type, const char *data)
  25. {
  26.     struct authinfo *aip;
  27.     char buf[2048], *username, *password;
  28.     
  29.     aip = s_malloc(sizeof(*aip));
  30.     
  31.     aip->type = s_strdup(type);
  32.     aip->data = s_strdup(data);
  33.     /* We only handle the Basic authentication type for now */
  34.     if (strcasecmp(aip->type, "basic") != 0)
  35. return aip;
  36.     if (!base64_decode(data, buf, sizeof(buf)))
  37. return aip;
  38.     username = buf;
  39.     password = strchr(buf, ':');
  40.     if (password)
  41. *password++ = '';
  42.     aip->u.basic.username = s_strdup(username);
  43.     aip->u.basic.password = s_strdup(password);
  44.     aip->xinfo = NULL;
  45.     aip->xfree = NULL;
  46.     aip->xsetenv = NULL;
  47.     return aip;
  48. }
  49. /* Release an authinfo structure */
  50. void auth_free(struct authinfo *aip)
  51. {
  52.     if (aip == NULL)
  53. return;
  54.     if (aip->type && strcasecmp(aip->type, "basic") == 0)
  55.     {
  56. s_free(aip->u.basic.username);
  57. s_free(aip->u.basic.password);
  58.     }
  59.     
  60.     s_free(aip->type);
  61.     s_free(aip->data);
  62.     
  63.     if (aip->xfree)
  64. (*aip->xfree)(aip->xinfo);
  65.     
  66.     s_free(aip->validated_username);
  67.     s_free(aip);
  68. }
  69. /* Get the authentication information from the HTTP MIME Headers */
  70. struct authinfo *auth_get(struct httpinfo *hip)
  71. {
  72.     char *auth, *type, *data, *authinfo, *cp;
  73.     int alen;
  74.     
  75.     
  76.     /* Is the request coming with an "Authorization:" header? */
  77.     auth = mime_getheader(hip->mip, "AUTHORIZATION", 1);
  78.     if (auth == NULL)
  79. return NULL;
  80.     if ( debug > 8 ) 
  81. fprintf(stderr,"Authorization: %sn",auth);
  82.     S_STRALLOCA(auth, &authinfo, 0, &alen);
  83.     type = strtok_r(authinfo, " t", &cp);
  84.     data = strtok_r(NULL, " t", &cp);
  85.     return auth_new(type, data);
  86. }
  87. struct table *auth_handlers_table = NULL;
  88. static int get_acl(int fd,
  89.    char *pattern,
  90.    int psize,
  91.    int *value,
  92.    urlinfo_t *uip )
  93. {
  94.     char buf[2048], *cp, *tok;
  95.     int key;
  96.     
  97.   Loop:
  98.     if (fd_gets(buf, sizeof(buf), fd) == NULL)
  99. return 0;
  100.     cp = strchr(buf, '#');
  101.     if (cp)
  102. *cp = '';
  103.     
  104.     cp = buf;
  105.     while (s_isspace(*cp))
  106. ++cp;
  107.     if (*cp == '')
  108. goto Loop;
  109.     tok = strtok_r(buf, " trn", &cp);
  110.     if (tok == NULL)
  111.     {
  112. syslog(LOG_ERR, "Invalid ACL file (%s) type entry: %s",
  113.        uip->access.path, tok);
  114. goto Loop;
  115.     }
  116.     if (strcmp(tok, "address") == 0)
  117. key = 1;
  118.     else if (strcmp(tok, "host") == 0)
  119. key = 2;
  120.     else
  121. key = -1;
  122.     
  123.     tok = strtok_r(NULL, " trn", &cp);
  124.     if (tok == NULL)
  125.     {
  126. syslog(LOG_ERR, "Invalid ACL file (%s) pattern entry: %s",
  127.        uip->access.path, tok);
  128. goto Loop;
  129.     }
  130.     s_strcpy(pattern, psize, tok);
  131.     tok = strtok_r(NULL, " trn", &cp);
  132.     if (tok == NULL ||
  133. !(strcmp(tok, "allow") == 0 ||
  134.   strcmp(tok, "reject") == 0 ||
  135.   strcmp(tok, "auth") == 0 ))
  136.     {
  137. syslog(LOG_ERR, "Invalid ACL file (%s) value entry: %s",
  138.        uip->access.path, tok == NULL ? "<null>" : tok);
  139. goto Loop;
  140.     }
  141.     *value = (strcmp(tok, "allow") == 0) ? ACL_ALLOW : ACL_REJECT;
  142.     if ( strcmp(tok, "auth" ) == 0 ) 
  143.     {
  144. tok = strtok_r(NULL, " trn", &cp);
  145. if ( tok != NULL )
  146. {
  147.   uip->auth.source = s_strdup(tok);
  148.   *value = ACL_AUTHENTIFICATE;
  149.   if ( cp != NULL )
  150.      {
  151. uip->auth.realm = s_strdup(cp);
  152. if ( uip->auth.realm[strlen(uip->auth.realm)-1] == 'n' )
  153. uip->auth.realm[strlen(uip->auth.realm)-1]=0x00;
  154.      }
  155.   if ( debug > 7 )
  156.      fprintf(stderr,"ACL-auth: to=%s, realm=%sn",uip->auth.source, ( uip->auth.realm != NULL ) ? uip->auth.realm : "<NULL>" );
  157. }
  158.     }
  159.     else
  160. if ( uip->auth.source != NULL )
  161. {
  162. /*   fprintf(stderr,"Need to cleann"); */
  163.   s_free(uip->auth.source);
  164.   uip->auth.source=NULL;
  165. }
  166. /* This (above) might be a race condition ? Need to check that ! Better: */
  167. /* Select of type of auth to cip ? (not uip ?) */
  168. /* BUG RK TODO... */
  169.     return key;
  170. }
  171. int access_check(urlinfo_t *uip, struct connectioninfo *cip)
  172. {
  173.     char *address = NULL;
  174.     char *hostname = NULL;
  175.     int fd, value, key;
  176.     char pattern[256];
  177.     
  178.     dns_get(cip->client, NULL, &hostname, &address, NULL);
  179.     
  180.     fd = fd_open(uip->access.path, O_RDONLY);
  181.     if (fd == -1)
  182.     {
  183. syslog(LOG_ERR, "Unable to open ACL file: %s", uip->access.path);
  184. return 0;
  185.     }
  186.     while ((key = get_acl(fd, pattern, sizeof(pattern), &value, uip )) != 0)
  187.     {
  188. switch (key)
  189. {
  190.   case 1:
  191.     if (address && strmatch(address, pattern))
  192.     {
  193. fd_close(fd);
  194. return value;
  195.     }
  196.     break;
  197.   case 2:
  198.     if (hostname && strmatch(hostname, pattern))
  199.     {
  200. fd_close(fd);
  201. return value;
  202.     }
  203.     break;
  204.     
  205.   default:
  206.     goto Fail;
  207. }
  208.     }
  209.   Fail:
  210.     fd_close(fd);
  211.     
  212.     return 0;
  213. }
  214. static const char *auth_gethandler(const char *domain)
  215. {
  216.     int i;
  217.     int len;
  218.     
  219.     len = strlen(domain);
  220.     
  221.     if (auth_handlers_table)
  222.     {
  223. for (i = 0; i < auth_handlers_table->length; i++)
  224. {
  225.     char **pair = auth_handlers_table->value[i];
  226.     
  227.     if (debug > 3)
  228. fprintf(stderr, "       (Checking AUTH %s vs %s)n",
  229. domain, pair[0]);
  230.     if (strmatch(domain, pair[0]))
  231.     {
  232.         if (debug > 1)
  233.     fprintf(stderr, "      (AUTH %s -> Handler %s)n",
  234.     domain, pair[1]);
  235.     
  236. return pair[1];
  237.     }
  238. }
  239.     }
  240.     return NULL;
  241. }
  242. static int auth_call(const char *handler,
  243.      struct authinfo *aip, struct connectioninfo *cip,
  244.      const char *domain)
  245. {
  246.     struct modinfo *mp;
  247.     void *mkey;
  248.     int status;
  249.     char buf[2048];
  250.     
  251.     
  252.     while (*handler && *handler == '/')
  253. ++handler;
  254.     s_strcpy(buf, sizeof(buf), modules_home);
  255.     s_strcat(buf, sizeof(buf), "/");
  256.     s_strcat(buf, sizeof(buf), handler);
  257.     
  258.     mp = md_load(buf, &mkey);
  259.     if (mp == NULL)
  260. return 0;
  261.     if (mp->pm_auth)
  262. status = mp->pm_auth(aip, cip, domain);
  263.     else
  264. status = 0;
  265.     
  266.     md_release(mkey);
  267.     return status;
  268. }
  269. /*
  270. ** Check the authentication for a specific URL in a certain domain
  271. */
  272. int access_auth(struct httpinfo *hip, struct connectioninfo *cip,
  273. const char *domain)
  274. {
  275.     const char *handler;
  276.     int result = 0;
  277.     
  278.     if (hip == NULL || hip->mip == NULL || hip->aip == NULL)
  279. return 0;
  280.     
  281.     handler = auth_gethandler(domain);
  282.     if (handler)
  283.     {
  284. if (debug > 2)
  285.     fprintf(stderr, "*** Calling AUTH handler %sn", handler);
  286. result = auth_call(handler,
  287.    hip->aip, cip,
  288.    domain);
  289. if (result != 1)
  290.     result = 0;
  291.     }
  292.     return result;
  293. }