home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 September / CHIPCD_9_99.iso / software / serwery_www / sambar / _setup.1 / security.c < prev    next >
C/C++ Source or Header  |  1998-04-20  |  21KB  |  941 lines

  1. /*
  2. ** SECURITY
  3. **
  4. **      HTTP Wrapper for the Security Management Routines
  5. **
  6. **        Confidential Property of Tod Sambar
  7. **        (c) Copyright Tod Sambar 1996-1997
  8. **        All rights reserved.
  9. **
  10. **
  11. ** Public Functions:
  12. **
  13. **        security_init
  14. **        security_exit
  15. **        security_request
  16. **        security_connect
  17. **        security_filter
  18. **
  19. ** Note:
  20. **        By default, all objects placed in the sysadmin folder (under docs)
  21. **        are required to have system administrator access.  All other
  22. **        security features are implemented through external event handlers.
  23. **
  24. ** History:
  25. ** Chg#    Date    Description                                                Resp
  26. ** ----    -------    -------------------------------------------------------    ----
  27. **         4FEB97    Created                                                    sambar
  28. **         23APR97    Added network connect security                            sambar
  29. **         09APR97    Added AD/site security filtering                        sambar
  30. **         07JUL97    Added multiple users/groups on the security line        sambar
  31. */
  32.  
  33. #include    <stdio.h>
  34. #include    <stdlib.h>
  35. #include    <memory.h>
  36. #include    <string.h>
  37. #include    <ctype.h>
  38. #include    <security.h>
  39.  
  40. /*
  41. ** Local Functions
  42. */
  43. SA_RETCODE            security__load(SA_CTX *ctx, SA_VOID *argp, 
  44.                         SA_CHAR *name, SA_CHAR *value);
  45. static SA_INT        security__casecmp(SA_CHAR *str1, SA_CHAR *str2, 
  46.                         SA_INT len);
  47.  
  48. /*
  49. ** Show-security RPC parameters
  50. */
  51. static SA_RPCPARAM        showsecp [] =
  52. {
  53.     { "type",        1,    "Security filter to show." }
  54. };
  55.  
  56. /*
  57. ** Local Structures
  58. */
  59. typedef struct        security__entry
  60. {
  61.     SA_INT            id;
  62.     SA_CHAR            *symbol;
  63.     SA_CHAR            *descr;
  64.  
  65. } SECURITY_ENTRY;
  66.  
  67. /*
  68. ** Local Defines
  69. */
  70. #define DENIED_HEADER    "HTTP/1.0 404 Request denied.\nContent-type: text/html\n\n<HTML><BODY>"
  71. #define DENIED_BODY        "Request denied by Sambar Server Proxy filter.<P>"
  72. #define DENIED_FOOTER    "</BODY></HTML>"
  73.  
  74. static SECURITY_ENTRY    Security_entries[] =
  75. {
  76.     { SECURITY_REDIRECT,        "redirect",
  77.       "URI to Redirect / URL to Redirect to"  },
  78.     { SECURITY_RESTRICT,        "restrict",
  79.       "URI to Restrict / User or Group granted access" },
  80.     { SECURITY_DENY,            "deny",
  81.       "IP to deny access to / URL to redirect offending hosts to" },
  82.     { SECURITY_HTTPACCEPT,        "httpaccept",
  83.       "IP addresses to accept HTTP hosts from" },
  84.     { SECURITY_HTTPDENY,        "httpdeny",
  85.       "IP addresses of hosts to deny HTTP access to" },
  86.     { SECURITY_FTPACCEPT,        "ftpaccept",
  87.       "IP addresses to accept FTP hosts from" },
  88.     { SECURITY_FTPDENY,            "ftpdeny",
  89.       "IP addresses of hosts to deny FTP access to" },
  90.     { SECURITY_PROXYACCEPT,        "proxyaccept",
  91.       "IP addresses to accept Proxy hosts from" },
  92.     { SECURITY_PROXYDENY,        "proxydeny",
  93.       "IP addresses of hosts to deny Proxy access to" },
  94.     { SECURITY_HOSTFILTER,        "hostfilter",
  95.       "Hosts to restrict proxy requests from (AD/Content filtering)" },
  96.     { SECURITY_URLFILTER,        "urlfilter",
  97.       "URLs to restrict proxy requests from (AD/Content filtering)" },
  98.     { SECURITY_IPRESTRICT,        "iprestrict",
  99.       "URI to Restrict / IP Address(s) to grant access" },
  100.     { SECURITY_HOSTRESTRICT,    "hostrestrict",
  101.       "Hosts to restrict proxy requests to (WWW kiosks)" },
  102.     { SECURITY_URLRESTRICT,        "urlrestrict",
  103.       "URLs to restrict proxy requests to (WWW kiosks)" }
  104. };
  105.  
  106. #define NUM_ENTRIES     sizeof(Security_entries) / sizeof(SECURITY_ENTRY)
  107. static SECURITY            *Entries[NUM_ENTRIES];
  108.  
  109.  
  110.  
  111. /*
  112. **  SECURITY_INIT
  113. **
  114. **    Initialize the Security Rules for use by the Sambar Server plugins.
  115. **    Rules are only loaded at application initialization time and (as this
  116. **    is a threaded application) cannot be modified without a restart of 
  117. **    the server (or mutexing).
  118. **
  119. **
  120. **  Parameters:
  121. **    sactx        Sambar Server context
  122. **
  123. **  Returns:
  124. **    SA_SUCCEED | SA_FAIL
  125. */
  126. SA_RETCODE SA_PUBLIC
  127. security_init(sactx)
  128. SA_CTX        *sactx;
  129. {
  130.     SA_INT        i;
  131.  
  132.     for (i = 0; i < NUM_ENTRIES; i++)
  133.         Entries[i] = (SECURITY *)NULL;
  134.  
  135.     /* 
  136.     ** Load the security rules from the security.ini file
  137.     */
  138.     for (i = 0; i < NUM_ENTRIES; i++)
  139.     {
  140.         if (sa_props_load(sactx, "security.ini", 
  141.             Security_entries[i].symbol, &Security_entries[i].id, 
  142.             (SA_PROPFUNC)security__load) != SA_SUCCEED)
  143.         {
  144.             SA_CHAR        buffer[256];
  145.  
  146.             sprintf(buffer, "Failure loading [%s] security section.", 
  147.                 Security_entries[i].symbol);
  148.             sa_log(sactx, buffer);
  149.         }
  150.     }
  151.  
  152.     /* Initialize the "showsec" RPC                                        */
  153.     if (sa_cmd_init(sactx, "showsec", 
  154.         showsecp, sizeof(showsecp) / sizeof(SA_RPCPARAM),
  155.         SA_AUTHORIZATION_ADMIN, "Security rule display.", 
  156.         (SA_VOID *)security_showsec) != SA_SUCCEED)
  157.     {
  158.         sa_log(sactx, "Unable to initialize Security RPCs");
  159.         return (SA_FAIL);
  160.     }
  161.  
  162.     sa_log(sactx, "Security Interfaces Initialized");
  163.  
  164.     return (SA_SUCCEED);
  165. }
  166.  
  167. /*
  168. **  SECURITY_EXIT
  169. **
  170. **    Free the Security Rules.
  171. **
  172. **  Parameters:
  173. **    sactx        Sambar Server context
  174. **
  175. **  Returns:
  176. **    SA_SUCCEED | SA_FAIL
  177. */
  178. SA_RETCODE SA_PUBLIC
  179. security_exit(sactx)
  180. SA_CTX        *sactx;
  181. {
  182.     SA_INT        i;
  183.     SECURITY    *snext;
  184.     SECURITY    *security;
  185.     ENTRY        *enext;
  186.     ENTRY        *entry;
  187.  
  188.     /* 
  189.     ** Free the security rules previously loaded from the security.ini file
  190.     */
  191.     for (i = 0; i < NUM_ENTRIES; i++)
  192.     {
  193.         security = Entries[i];
  194.         while (security != (SECURITY *)NULL)
  195.         {
  196.             snext = security->next;
  197.             free(security->name);
  198.  
  199.             entry = security->entries;
  200.             while (entry != (ENTRY *)NULL)
  201.             {
  202.                 enext = entry->next;
  203.                 free(entry->value);
  204.                 free(entry);
  205.                 entry = enext;
  206.             }
  207.  
  208.             free(security);
  209.             security = snext;
  210.         }
  211.     }
  212.  
  213.     sa_log(sactx, "Security Interfaces Exited");
  214.  
  215.     return (SA_SUCCEED);
  216. }
  217.  
  218. /*
  219. **  SECURITY_REQUEST
  220. **
  221. **    Determine if the request should be fulfilled.
  222. **
  223. **  Parameters:
  224. **    sactx        Sambar Server context
  225. **    saconn        Client connection handle.
  226. **    uri            The URI associated with the request.
  227. **    urilen        The length of the URI string.
  228. **    params        The parameters associated with the request.
  229. **    infop        The error status returned on failure.
  230. **
  231. **  Returns:
  232. **    SA_SUCCEED | SA_FAIL
  233. */
  234. SA_RETCODE SA_PUBLIC
  235. security_request(sactx, saconn, uri, urilen, params, infop)
  236. SA_CTX        *sactx;
  237. SA_CONN        *saconn;
  238. SA_CHAR        *uri;
  239. SA_INT        urilen;
  240. SA_PARAMS    *params;
  241. SA_INT        *infop;
  242. {
  243.     SA_BOOL        found;
  244.     SA_INT        namelen;
  245.     SA_CHAR        name[40];
  246.     SA_INT        pwdlen;
  247.     SA_CHAR        pwd[40];
  248.     ENTRY        *entry;
  249.     SECURITY    *security;
  250.  
  251.     /* 
  252.     ** REDIRECT
  253.     */
  254.     security = Entries[SECURITY_REDIRECT];
  255.     while (security != (SECURITY *)NULL)
  256.     {
  257.         if ((urilen >= security->namelen) && 
  258.             (strnicmp(uri, security->name, security->namelen) == 0))
  259.         {
  260.             *infop = SA_E_REDIRECT;
  261.             entry = security->entries;
  262.             (SA_VOID)sa_conn_redirect(saconn, entry->value, 
  263.                 "Request redirected.", SA_NULLTERM);
  264.             return (SA_FAIL);
  265.         }
  266.  
  267.         security = security->next;
  268.     }
  269.  
  270.     /*
  271.     ** RESTRICT
  272.     */
  273.     security = Entries[SECURITY_RESTRICT];
  274.     while (security != (SECURITY *)NULL)
  275.     {
  276.         SA_PASSWD    passwd;
  277.  
  278.         if ((urilen >= security->namelen) && 
  279.             (strnicmp(uri, security->name, security->namelen) == 0))
  280.         {
  281.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_NAME, name, 40,
  282.                 &namelen) != SA_SUCCEED)
  283.             {
  284.                 *infop = SA_E_INVALIDLOGIN;
  285.                 return (SA_FAIL);
  286.             }
  287.  
  288.             /* Now lookup the name/password in the passwd file            */
  289.             if (sa_passwd_lookup(sactx, name, namelen, &passwd) != SA_SUCCEED)
  290.             {
  291.                 *infop = SA_E_INVALIDLOGIN;
  292.                 return (SA_FAIL);
  293.             }
  294.  
  295.             /* Get the password and verify the match                    */
  296.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_PASSWORD, pwd, 40,
  297.                 &pwdlen) != SA_SUCCEED)
  298.             {
  299.                 *infop = SA_E_INVALIDLOGIN;
  300.                 return (SA_FAIL);
  301.             }
  302.  
  303.             if ((passwd.passwordlen != pwdlen) ||
  304.                 (strncmp(passwd.password, pwd, pwdlen) != 0))
  305.             {
  306.                 *infop = SA_E_INVALIDLOGIN;
  307.                 return (SA_FAIL);
  308.             }
  309.  
  310.             /* 
  311.             ** Lastly, verify the security entry(s) match either the name
  312.             ** or group name of the user.
  313.             */
  314.             found = 0;
  315.             entry = security->entries;
  316.             while ((!found) && (entry != (ENTRY *)NULL))
  317.             {
  318.                 /* Match with the username?                                */
  319.                 if ((namelen == entry->valuelen) &&
  320.                      (memcmp(entry->value, name, namelen) == 0))
  321.                 {
  322.                     found = 1;
  323.                     continue;
  324.                 }
  325.  
  326.                 /* Match with the user group?                            */
  327.                 if ((passwd.grouplen == entry->valuelen) &&
  328.                     (memcmp(entry->value, passwd.group, passwd.grouplen) == 0))
  329.                 {
  330.                     found = 1;
  331.                     continue;
  332.                 }
  333.  
  334.                 entry = entry->next;
  335.             }
  336.  
  337.             if (!found)
  338.             {
  339.                 *infop = SA_E_INVALIDLOGIN;
  340.                 return (SA_FAIL);
  341.             }
  342.         }
  343.  
  344.         security = security->next;
  345.     }
  346.     
  347.     /*
  348.     ** DENY
  349.     */
  350.     if ((Entries[SECURITY_DENY] != (SECURITY *)NULL) &&
  351.         (sa_conn_props(saconn, SA_GET, SA_CONNPROP_HOST, name, 40,
  352.         &namelen) == SA_SUCCEED))
  353.     {
  354.         security = Entries[SECURITY_DENY];
  355.         while (security != (SECURITY *)NULL)
  356.         {
  357.             if ((namelen >= security->namelen) && 
  358.                 (strncmp(name, security->name, security->namelen) == 0))
  359.             {
  360.                 entry = security->entries;
  361.                 *infop = SA_E_REDIRECT;
  362.                 (SA_VOID)sa_conn_redirect(saconn, entry->value, 
  363.                     "Request redirected.", SA_NULLTERM);
  364.                 return (SA_FAIL);
  365.             }
  366.  
  367.             security = security->next;
  368.         }
  369.     }
  370.  
  371.     /*
  372.     ** IP-RESTRICT
  373.     */
  374.     security = Entries[SECURITY_IPRESTRICT];
  375.     while (security != (SECURITY *)NULL)
  376.     {
  377.         if ((urilen >= security->namelen) && 
  378.             (strnicmp(uri, security->name, security->namelen) == 0))
  379.         {
  380.             /* Get the IP address of the client.                        */
  381.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_IPADDR, name, 20,
  382.                 &namelen) != SA_SUCCEED)
  383.             {
  384.                 return (SA_FAIL);
  385.             }
  386.  
  387.             /* 
  388.             ** Lastly, verify the security entry(s) match the IP
  389.             ** address of the client.
  390.             */
  391.             found = 0;
  392.             entry = security->entries;
  393.             while ((!found) && (entry != (ENTRY *)NULL))
  394.             {
  395.                 if (sa_wildcmp(sactx, entry->value, entry->valuelen, 
  396.                     name, namelen) == 0)
  397.                 {
  398.                     found = 1;
  399.                     continue;
  400.                 }
  401.  
  402.                 entry = entry->next;
  403.             }
  404.  
  405.             if (!found)
  406.             {
  407.                 *infop = SA_E_FORBIDDEN;
  408.                 return (SA_FAIL);
  409.             }
  410.         }
  411.  
  412.         security = security->next;
  413.     }
  414.     
  415.  
  416.     return (SA_SUCCEED);
  417. }
  418.  
  419. /*
  420. **  SECURITY_CONNECT
  421. **
  422. **    Determine if the connection should be allowed.
  423. **
  424. **  Parameters:
  425. **    sactx        Sambar Server context
  426. **    ipaddr        The IP address of the client requesting a connection.
  427. **    servertype    The server the client is attempting to connect to.
  428. **
  429. **  Returns:
  430. **    SA_SUCCEED | SA_FAIL
  431. */
  432. SA_RETCODE SA_PUBLIC
  433. security_connect(sactx, ipaddr, servertype)
  434. SA_CTX        *sactx;
  435. SA_CHAR        *ipaddr;
  436. SA_INT        servertype;
  437. {
  438.     SA_INT        denyid;
  439.     SA_INT        acceptid;
  440.     SA_INT        ipaddrlen;
  441.     SA_BOOL        found;
  442.     SA_CHAR        *server;
  443.     SECURITY    *security;
  444.     SA_CHAR        buffer[256];
  445.  
  446.     /* Initialization                                                    */
  447.     ipaddrlen = strlen(ipaddr);
  448.  
  449.     switch((int)servertype)
  450.     {
  451.     case SA_SERVERTYPE_HTTP:
  452.         server = "HTTP";
  453.         denyid = SECURITY_HTTPDENY;
  454.         acceptid = SECURITY_HTTPACCEPT;
  455.         break;
  456.  
  457.     case SA_SERVERTYPE_FTP:
  458.         server = "FTP";
  459.         denyid = SECURITY_FTPDENY;
  460.         acceptid = SECURITY_FTPACCEPT;
  461.         break;
  462.  
  463.     case SA_SERVERTYPE_HTTPPROXY:
  464.     case SA_SERVERTYPE_SMTPPROXY:
  465.     case SA_SERVERTYPE_POP3PROXY:
  466.     case SA_SERVERTYPE_IMAP4PROXY:
  467.     case SA_SERVERTYPE_BRIDGEPROXY:
  468.     case SA_SERVERTYPE_NNTPPROXY:
  469.     case SA_SERVERTYPE_TELNETD:
  470.         server = "PROXY";
  471.         denyid = SECURITY_PROXYDENY;
  472.         acceptid = SECURITY_PROXYACCEPT;
  473.         break;
  474.  
  475.     default:
  476.         sprintf(buffer, "NETCONNECT: Unrecognized server (%d)", servertype);
  477.         sa_log(sactx, buffer);
  478.         return (SA_FAIL);
  479.     }
  480.  
  481.     /* 
  482.     ** NETACCEPT
  483.     **
  484.     ** The client must be in the accept list.
  485.     */
  486.     found = 0;
  487.     security = Entries[acceptid];
  488.     while ((!found) && (security != (SECURITY *)NULL))
  489.     {
  490.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  491.             ipaddr, ipaddrlen) == 0)
  492.         {
  493.             found = 1;
  494.             continue;
  495.         }
  496.  
  497.         security = security->next;
  498.     }
  499.  
  500.     if (!found)
  501.     {
  502.         sprintf(buffer, 
  503.             "NETCONNECT: Client %s not in accept list for server %s.",
  504.             ipaddr, server);
  505.         sa_log(sactx, buffer);
  506.         return (SA_FAIL);
  507.     }
  508.  
  509.     /* 
  510.     ** NETDENY
  511.     **
  512.     ** The client cannot be in the deny list.
  513.     */
  514.     security = Entries[denyid];
  515.     while (security != (SECURITY *)NULL)
  516.     {
  517.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  518.             ipaddr, ipaddrlen) == 0)
  519.         {
  520.             sprintf(buffer, 
  521.                 "NETCONNECT: Client %s is in deny list for server %s.", 
  522.                 ipaddr, server);
  523.             sa_log(sactx, buffer);
  524.             return (SA_FAIL);
  525.         }
  526.  
  527.         security = security->next;
  528.     }
  529.  
  530.     return (SA_SUCCEED);
  531. }
  532.  
  533. /*
  534. **  SECURITY_FILTER
  535. **
  536. **    Filter all HTTP Proxy requests.
  537. **
  538. **  If the requested URL is found in the [httpfilter] section, either 
  539. **    return the file specified in the file in response to the request, 
  540. **    or return a 404 request denied message if no file is specified.
  541. **
  542. **  If the requested URL is NOT found in the [httprestrict] section, 
  543. **    return a 404 request denied message.
  544. **
  545. **  If the requested URL is found in the [urlfilter] section, 
  546. **    return a 404 request denied message.
  547. **
  548. **
  549. **  Parameters:
  550. **    sactx        Sambar Server context
  551. **
  552. **  Returns:
  553. **    SA_SUCCEED | SA_FAIL
  554. */
  555. SA_RETCODE SA_PUBLIC
  556. security_filter(sactx, saconn, host, hostlen, url, urllen)
  557. SA_CTX        *sactx;
  558. SA_CONN        *saconn;
  559. SA_CHAR        *host;
  560. SA_INT        hostlen;
  561. SA_CHAR        *url;
  562. SA_INT        urllen;
  563. {
  564.     SA_INT        i;
  565.     SA_INT        urlcaselen;
  566.     SA_BOOL        found;
  567.     SECURITY    *security;
  568.     SA_CHAR        urlcase[2048];
  569.  
  570.     /*
  571.     ** Convert the host and URL to lower case.
  572.     */
  573.     for (i = 0; i < hostlen; i++)
  574.         host[i] = tolower(host[i]);
  575.  
  576.     urlcaselen = 0;
  577.     while ((urlcaselen < urllen) && (urlcaselen < 1024))
  578.     {
  579.         urlcase[urlcaselen] = tolower(url[urlcaselen]);
  580.         urlcaselen++;
  581.     }
  582.  
  583.     urlcase[urlcaselen] = '\0';
  584.  
  585.     security = Entries[SECURITY_HOSTFILTER];
  586.     while (security != (SECURITY *)NULL)
  587.     {
  588.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  589.             host, hostlen) == 0)
  590.         {
  591.             ENTRY        *entry;
  592.  
  593.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  594.             (SA_VOID)sa_conn_send(saconn, DENIED_BODY, SA_NULLTERM);
  595.  
  596.             entry = security->entries;
  597.             if (hostlen + entry->valuelen < 1000)
  598.             {
  599.                 sprintf(buffer, "HTTPPROXY: Host %s blocked by filter: %s", 
  600.                     host, entry->value);
  601.                 (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  602.                 sa_log(sactx, buffer);
  603.             }
  604.  
  605.             (SA_VOID)sa_conn_send(saconn, DENIED_FOOTER, SA_NULLTERM);
  606.  
  607.             return (SA_FAIL);
  608.         }
  609.  
  610.         security = security->next;
  611.     }
  612.  
  613.     security = Entries[SECURITY_URLFILTER];
  614.     while (security != (SECURITY *)NULL)
  615.     {
  616.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  617.             urlcase, urlcaselen) == 0)
  618.         {
  619.             ENTRY        *entry;
  620.  
  621.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  622.             (SA_VOID)sa_conn_send(saconn, DENIED_BODY, SA_NULLTERM);
  623.  
  624.             entry = security->entries;
  625.             if (urlcaselen + entry->valuelen < 1000)
  626.             {
  627.                 sprintf(buffer, "HTTPPROXY: URL %s blocked by filter: %s", 
  628.                     urlcase, entry->value);
  629.                 (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  630.                 sa_log(sactx, buffer);
  631.             }
  632.  
  633.             (SA_VOID)sa_conn_send(saconn, DENIED_FOOTER, SA_NULLTERM);
  634.  
  635.             return (SA_FAIL);
  636.         }
  637.  
  638.         security = security->next;
  639.     }
  640.  
  641.     /* 
  642.     ** If a [hostrestrict] entry is found, the host must match 
  643.     ** an entry on the list provided or it will be denied.
  644.     */
  645.     security = Entries[SECURITY_HOSTRESTRICT];
  646.     if (security != (SECURITY *)NULL)
  647.     {
  648.         found = 0;
  649.         while ((!found) && (security != (SECURITY *)NULL))
  650.         {
  651.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  652.                 host, hostlen) == 0)
  653.             {
  654.                 found = 1;
  655.                 continue;
  656.             }
  657.  
  658.             security = security->next;
  659.         }
  660.  
  661.         if (!found)
  662.         {
  663.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  664.             (SA_VOID)sa_conn_send(saconn, DENIED_BODY, SA_NULLTERM);
  665.             sprintf(buffer, "HTTPPROXY: Host '%s' not on [hostrestrict] list", 
  666.                     host);
  667.             (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  668.             sa_log(sactx, buffer);
  669.             (SA_VOID)sa_conn_send(saconn, DENIED_FOOTER, SA_NULLTERM);
  670.             return (SA_FAIL);
  671.         }
  672.     }
  673.  
  674.     /* 
  675.     ** If a [urlrestrict] entry is found, the URL must match 
  676.     ** an entry on the list provided or it will be denied.
  677.     */
  678.     security = Entries[SECURITY_URLRESTRICT];
  679.     if (security != (SECURITY *)NULL)
  680.     {
  681.         found = 0;
  682.         while ((!found) && (security != (SECURITY *)NULL))
  683.         {
  684.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  685.                 urlcase, urlcaselen) == 0)
  686.             {
  687.                 found = 1;
  688.                 continue;
  689.             }
  690.  
  691.             security = security->next;
  692.         }
  693.  
  694.         if (!found)
  695.         {
  696.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  697.             (SA_VOID)sa_conn_send(saconn, DENIED_BODY, SA_NULLTERM);
  698.             sprintf(buffer, "HTTPPROXY: URL '%s' not on [urlrestrict] list", 
  699.                     urlcase);
  700.             (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  701.             sa_log(sactx, buffer);
  702.             (SA_VOID)sa_conn_send(saconn, DENIED_FOOTER, SA_NULLTERM);
  703.             return (SA_FAIL);
  704.         }
  705.     }
  706.  
  707.     /* HTTP Request should be allowed through.                            */
  708.     return (SA_SUCCEED);
  709. }
  710.  
  711. /*
  712. **  SECURITY__LOAD
  713. **
  714. **    Load a single security rule.
  715. **
  716. **  Parameters:
  717. **    sactx        Sambar Server context
  718. **    argp        Security parameter.
  719. **    name        Left hand argument.
  720. **    value        Right hand argument.
  721. **
  722. **  Returns:
  723. **    SA_SUCCEED | SA_FAIL
  724. */
  725. SA_RETCODE
  726. security__load(sactx, argp, name, value)
  727. SA_CTX        *sactx;
  728. SA_VOID        *argp;
  729. SA_CHAR        *name;
  730. SA_CHAR        *value;
  731. {
  732.     SA_INT        valuelen;
  733.     ENTRY        *entry;
  734.     SECURITY    *security;
  735.  
  736.     security = (SECURITY *)malloc(sizeof(SECURITY));
  737.     if (security == (SECURITY *)NULL)
  738.         return (SA_FAIL);
  739.  
  740.     memset(security, 0, sizeof(SECURITY));
  741.     security->namelen = strlen(name);
  742.     valuelen = strlen(value);
  743.  
  744.     if ((security->namelen == 0) || (valuelen == 0))
  745.         return (SA_FAIL);
  746.  
  747.     security->name = strdup(name);
  748.  
  749.     /* Restriction & IP-restriction lists have multiple entries            */
  750.     if ((*(SA_INT *)argp == SECURITY_RESTRICT) ||
  751.         (*(SA_INT *)argp == SECURITY_IPRESTRICT))
  752.     {
  753.         SA_INT        pos;
  754.         SA_INT        head;
  755.  
  756.         pos = 0;
  757.         while (pos < valuelen)
  758.         {
  759.             head = pos;
  760.             while ((pos < valuelen) && !isspace(value[pos]))
  761.                 pos++;
  762.  
  763.             value[pos] = '\0';
  764.  
  765.             entry = (ENTRY *)malloc(sizeof(ENTRY));
  766.             if (entry == (ENTRY *)NULL)
  767.                 return (SA_FAIL);
  768.  
  769.             memset(entry, 0, sizeof(ENTRY));
  770.             entry->value = strdup(&value[head]);
  771.             entry->valuelen = pos - head;;
  772.             entry->next = security->entries;
  773.             security->entries = entry;
  774.  
  775.             pos++;
  776.             while ((pos < valuelen) && isspace(value[pos]))
  777.                 pos++;
  778.         }
  779.     }
  780.     else
  781.     {
  782.         entry = (ENTRY *)malloc(sizeof(ENTRY));
  783.         if (entry == (ENTRY *)NULL)
  784.             return (SA_FAIL);
  785.  
  786.         memset(entry, 0, sizeof(ENTRY));
  787.         entry->valuelen = valuelen;
  788.         entry->value = strdup(value);
  789.         security->entries = entry;
  790.     }
  791.  
  792.     security->next = Entries[*(SA_INT *)argp];
  793.     Entries[*(SA_INT *)argp] = security;
  794.  
  795.     return (SA_SUCCEED);
  796. }
  797.  
  798. /*
  799. **  SECURITY_SHOWSEC
  800. **
  801. **    Show the security associated with a particular symbol.
  802. **
  803. **  Parameters:
  804. **    sactx        Sambar Server context
  805. **    saconn        Sambar Server connection
  806. **    saparams    RPC Parameters
  807. **    infop        Error parameters
  808. **
  809. **  Returns:
  810. **    SA_SUCCEED | SA_FAIL
  811. */
  812. SA_RETCODE SA_PUBLIC
  813. security_showsec(sactx, saconn, saparams, infop)
  814. SA_CTX        *sactx;
  815. SA_CONN        *saconn;
  816. SA_PARAMS    *saparams;
  817. SA_INT        *infop;
  818. {
  819.     SA_INT        i;
  820.     SA_BOOL        found;
  821.     SA_INT        datalen;
  822.     SA_CHAR        *data;
  823.     ENTRY        *entry;
  824.     SECURITY    *security;
  825.     SA_CHAR        buffer[1024];
  826.  
  827.     if ((sa_param(sactx, saparams, "type", &data, &datalen) != SA_SUCCEED) ||
  828.         (datalen == 0))
  829.     {
  830.         /* No report type given                                            */
  831.         return (SA_SUCCEED);
  832.     }
  833.  
  834.     i = 0;
  835.     found = 0;
  836.     while ((i < NUM_ENTRIES) && (!found))
  837.     {
  838.         if (strcmp(Security_entries[i].symbol, (SA_CHAR *)data) == 0)
  839.             found = 1;
  840.         else
  841.             i++;
  842.     }
  843.  
  844.     if (!found)
  845.     {
  846.         *infop = SA_E_INVALIDDATA;
  847.         return (SA_FAIL);
  848.     }
  849.  
  850.     sprintf(buffer, "<FONT SIZE=+1><B>%s</B></FONT><P>\n", 
  851.         Security_entries[i].descr);
  852.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  853.         return (SA_FAIL);
  854.  
  855.     security = Entries[i];
  856.     if (security == (SECURITY *)NULL)
  857.     {
  858.         if (sa_conn_send(saconn, "<I>No Security Controls defined.", 
  859.             SA_NULLTERM) != SA_SUCCEED)
  860.         {
  861.             return (SA_FAIL);
  862.         }
  863.  
  864.         return (SA_SUCCEED);
  865.     }
  866.  
  867.     if (sa_conn_send(saconn, "<TABLE border=1 cellspacing=4>\n", SA_NULLTERM) 
  868.         != SA_SUCCEED)
  869.     {
  870.         return (SA_FAIL);
  871.     }
  872.  
  873.     while (security != (SECURITY *)NULL)
  874.     {
  875.         sprintf(buffer, "<TR><TD>%s</TD><TD>", security->name);
  876.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  877.             return (SA_FAIL);
  878.  
  879.         entry = security->entries;
  880.         while (entry != (ENTRY *)NULL)
  881.         {
  882.             sprintf(buffer, "%s ", entry->value);
  883.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  884.                 return (SA_FAIL);
  885.  
  886.             entry = entry->next;
  887.         }
  888.  
  889.         if (sa_conn_send(saconn, "</TD></TR>\n", SA_NULLTERM) != SA_SUCCEED)
  890.             return (SA_FAIL);
  891.  
  892.         security = security->next;
  893.     }
  894.  
  895.     if (sa_conn_send(saconn, "</TABLE>\n", SA_NULLTERM) != SA_SUCCEED)
  896.         return (SA_FAIL);
  897.  
  898.     return (SA_SUCCEED);
  899. }
  900.  
  901. /*
  902. **  SECURITY__CASECMP
  903. **
  904. **    Compare two case-insensitive strings.
  905. **
  906. **  Parameters:
  907. **    str1        String to compare.
  908. **    str2        String to compare.
  909. **    len            Length of the comparison.
  910. **
  911. **  Returns:
  912. **    SA_INT
  913. */
  914. static SA_INT
  915. security__casecmp(str1, str2, len)
  916. SA_CHAR        *str1;
  917. SA_CHAR        *str2;
  918. SA_INT        len;
  919. {
  920.     SA_INT        i;
  921.     SA_INT        diff;
  922.  
  923.     if (len == 0)
  924.         return (0);
  925.  
  926.     i = 0;
  927.     while (i < len)
  928.     {
  929.         if ((str1[i] == '\0') || (str2[i] == '\0'))
  930.             return (str1[i] - str2[i]);
  931.  
  932.         diff = tolower(str1[i]) - tolower(str2[i]);
  933.         if (diff != 0)
  934.             return (diff);
  935.  
  936.         i++;
  937.     }
  938.  
  939.     return (0);
  940. }
  941.