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