home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 February / PCWorld_2003-02_cd.bin / Komunik / sambar / sambar53b3.exe / samples / source / security.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-29  |  28.4 KB  |  1,209 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. #ifndef    WIN32
  43. #define stricmp        strcasecmp
  44. #define strnicmp    strncasecmp
  45. extern int strcasecmp(const char *, const char *);
  46. extern int strncasecmp(const char *, const char *, int);
  47. extern char *strdup(const char *);
  48. #endif    /* WIN32 */
  49.  
  50. /*
  51. ** Local Functions
  52. */
  53. SA_RETCODE            security__load(SA_CTX *ctx, SA_VOID *argp, 
  54.                         SA_CHAR *name, SA_CHAR *value);
  55.  
  56. /*
  57. ** Show-security RPC parameters
  58. */
  59. static SA_RPCPARAM        showsecp [] =
  60. {
  61.     { "type",        1,    "Security filter to show." }
  62. };
  63.  
  64. /*
  65. ** Local Structures
  66. */
  67. typedef struct        security__entry
  68. {
  69.     SA_INT            id;
  70.     SA_CHAR            *symbol;
  71.     SA_CHAR            *descr;
  72.  
  73. } SECURITY_ENTRY;
  74.  
  75. /*
  76. ** Local Defines
  77. */
  78. #define DENIED_HEADER    "HTTP/1.0 404 Request denied.\nContent-type: text/html\n\n"
  79.  
  80. static SECURITY_ENTRY    Security_entries[] =
  81. {
  82.     { SECURITY_REDIRECT,        "redirect",
  83.       "URI to Redirect / URL to Redirect to"  },
  84.     { SECURITY_RESTRICT,        "restrict",
  85.       "URI to Restrict / User or Group granted access" },
  86.     { SECURITY_DENY,            "deny",
  87.       "IP to deny access to / URL to redirect offending hosts to" },
  88.     { SECURITY_HTTPACCEPT,        "httpaccept",
  89.       "IP addresses to accept HTTP hosts from" },
  90.     { SECURITY_HTTPDENY,        "httpdeny",
  91.       "IP addresses of hosts to deny HTTP access to" },
  92.     { SECURITY_FTPACCEPT,        "ftpaccept",
  93.       "IP addresses to accept FTP hosts from" },
  94.     { SECURITY_FTPDENY,            "ftpdeny",
  95.       "IP addresses of hosts to deny FTP access to" },
  96.     { SECURITY_PROXYACCEPT,        "proxyaccept",
  97.       "IP addresses to accept Proxy hosts from" },
  98.     { SECURITY_PROXYDENY,        "proxydeny",
  99.       "IP addresses of hosts to deny Proxy access to" },
  100.     { SECURITY_HOSTFILTER,        "hostfilter",
  101.       "Hosts to restrict proxy requests from (AD/Content filtering)" },
  102.     { SECURITY_URLFILTER,        "urlfilter",
  103.       "URLs to restrict proxy requests from (AD/Content filtering)" },
  104.     { SECURITY_IPRESTRICT,        "iprestrict",
  105.       "URI to Restrict / IP Address(s) to grant access" },
  106.     { SECURITY_HOSTRESTRICT,    "hostrestrict",
  107.       "Hosts to restrict proxy requests to (WWW kiosks)" },
  108.     { SECURITY_URLRESTRICT,        "urlrestrict",
  109.       "URLs to restrict proxy requests to (WWW kiosks)" },
  110.     { SECURITY_MAILACCEPT,        "mailaccept",
  111.       "IP addresses to accept Mail (SMTP/POP3/IMAP4) hosts from" },
  112.     { SECURITY_MAILDENY,        "maildeny",
  113.       "IP addresses of hosts to deny Mail (SMTP/POP3/IMAP4) access to" },
  114.     { SECURITY_DNSACCEPT,        "dnsaccept",
  115.       "IP addresses to accept DNS requests from" },
  116.     { SECURITY_DNSDENY,            "dnsdeny",
  117.       "IP addresses of hosts to deny DNS access to" },
  118.     { SECURITY_SIPACCEPT,        "sipaccept",
  119.       "IP addresses to accept SIP requests from" },
  120.     { SECURITY_SIPDENY,            "sipdeny",
  121.       "IP addresses of hosts to deny SIP access to" },
  122.     { SECURITY_HOSTREDIRECT,    "hostredirect",
  123.       "Hosts to redirect requests to (vhost management)" },
  124.     { SECURITY_SITEREDIRECT,    "siteredirect",
  125.       "Hosts to redirect requests to; original URL is appended" },
  126.     { SECURITY_TFTPACCEPT,        "tftpaccept",
  127.       "IP addresses to accept TFTP requests from" },
  128.     { SECURITY_TFTPDENY,        "tftpdeny",
  129.       "IP addresses of hosts to deny TFTP access to" },
  130. };
  131.  
  132. #define NUM_ENTRIES     sizeof(Security_entries) / sizeof(SECURITY_ENTRY)
  133. static SECURITY            *Entries[NUM_ENTRIES];
  134. static SECURITY            *TmpEntries[NUM_ENTRIES];
  135.  
  136.  
  137.  
  138. /*
  139. **  SECURITY_INIT
  140. **
  141. **    Initialize the Security Rules for use by the Sambar Server plugins.
  142. **    Rules are only loaded at application initialization time and (as this
  143. **    is a threaded application) cannot be modified without a restart of 
  144. **    the server (or mutexing).
  145. **
  146. **
  147. **  Parameters:
  148. **    sactx        Sambar Server context
  149. **
  150. **  Returns:
  151. **    SA_SUCCEED | SA_FAIL
  152. */
  153. SA_RETCODE SA_PUBLIC
  154. security_init(sactx)
  155. SA_CTX        *sactx;
  156. {
  157.     SA_INT        i;
  158.     SA_CHAR        buffer[256];
  159.  
  160.     /* 
  161.     ** Load the security rules from the security.ini file
  162.     */
  163.     for (i = 0; i < NUM_ENTRIES; i++)
  164.     {
  165.         TmpEntries[i] = (SECURITY *)NULL;
  166.  
  167.         if (sa_props_load(sactx, "security.ini", 
  168.             Security_entries[i].symbol, &Security_entries[i].id, 
  169.             (SA_PROPFUNC)security__load) != SA_SUCCEED)
  170.         {
  171.             sprintf(buffer, "Failure loading [%s] security section.", 
  172.                 Security_entries[i].symbol);
  173.             sa_log2(sactx, SA_LOG_ERROR, buffer);
  174.         }
  175.  
  176.         Entries[i] = TmpEntries[i];
  177.     }
  178.  
  179.     /* Initialize the "showsec" RPC                                        */
  180.     if (sa_cmd_init(sactx, "showsec", 
  181.         showsecp, sizeof(showsecp) / sizeof(SA_RPCPARAM),
  182.         SA_AUTHORIZATION_ADMIN, "Security rule display.", 
  183.         (SA_VOID *)security_showsec) != SA_SUCCEED)
  184.     {
  185.         sa_log2(sactx, SA_LOG_ERROR, "Unable to initialize Security RPCs");
  186.         return (SA_FAIL);
  187.     }
  188.  
  189.     if (sa_cmd_init(sactx, "reloadsec", (SA_RPCPARAM *)NULL, 0,
  190.         SA_AUTHORIZATION_ADMIN, "Reload security rules.", 
  191.         (SA_VOID *)security_reload) != SA_SUCCEED)
  192.     {
  193.         sa_log2(sactx, SA_LOG_ERROR, "Unable to initialize Security RPCs");
  194.         return (SA_FAIL);
  195.     }
  196.  
  197.     sa_log2(sactx, SA_LOG_TRACE, "Security Interfaces Initialized");
  198.  
  199.     return (SA_SUCCEED);
  200. }
  201.  
  202. /*
  203. **  SECURITY_EXIT
  204. **
  205. **    Free the Security Rules.
  206. **
  207. **  Parameters:
  208. **    sactx        Sambar Server context
  209. **
  210. **  Returns:
  211. **    SA_SUCCEED | SA_FAIL
  212. */
  213. SA_RETCODE SA_PUBLIC
  214. security_exit(sactx)
  215. SA_CTX        *sactx;
  216. {
  217.     SA_INT        i;
  218.     SECURITY    *snext;
  219.     SECURITY    *security;
  220.     ENTRY        *enext;
  221.     ENTRY        *entry;
  222.  
  223.     /* 
  224.     ** Free the security rules previously loaded from the security.ini file
  225.     */
  226.     for (i = 0; i < NUM_ENTRIES; i++)
  227.     {
  228.         security = Entries[i];
  229.         while (security != (SECURITY *)NULL)
  230.         {
  231.             snext = security->next;
  232.             free(security->name);
  233.  
  234.             entry = security->entries;
  235.             while (entry != (ENTRY *)NULL)
  236.             {
  237.                 enext = entry->next;
  238.                 free(entry->value);
  239.                 free(entry);
  240.                 entry = enext;
  241.             }
  242.  
  243.             free(security);
  244.             security = snext;
  245.         }
  246.     }
  247.  
  248.     sa_log2(sactx, SA_LOG_TRACE, "Security Interfaces Exited");
  249.  
  250.     return (SA_SUCCEED);
  251. }
  252.  
  253. /*
  254. **  SECURITY_REQUEST
  255. **
  256. **    Determine if the request should be fulfilled.
  257. **
  258. **  Parameters:
  259. **    sactx        Sambar Server context
  260. **    saconn        Client connection handle.
  261. **    uri            The URI associated with the request.
  262. **    urilen        The length of the URI string.
  263. **    params        The parameters associated with the request.
  264. **    infop        The error status returned on failure.
  265. **
  266. **  Returns:
  267. **    SA_SUCCEED | SA_FAIL
  268. */
  269. SA_RETCODE SA_PUBLIC
  270. security_request(sactx, saconn, uri, urilen, params, infop)
  271. SA_CTX        *sactx;
  272. SA_CONN        *saconn;
  273. SA_CHAR        *uri;
  274. SA_INT        urilen;
  275. SA_PARAMS    *params;
  276. SA_INT        *infop;
  277. {
  278.     SA_INT        pwdlen;
  279.     SA_INT        namelen;
  280.     SA_BOOL        ntauth;
  281.     SA_BOOL        sqlauth;
  282.     SA_BOOL        radiusauth;
  283.     SA_BOOL        found;
  284.     SA_BOOL        status;
  285.     ENTRY        *entry;
  286.     SECURITY    *security;
  287.     SA_CHAR        name[512];
  288.     SA_CHAR        pwd[60];
  289.     SA_CHAR        tmp[1024];
  290.     SA_PASSWD    passwd;
  291.  
  292.     ntauth = 0;
  293.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_NTAUTH, tmp, 30, 
  294.         (SA_INT *)NULL) == SA_SUCCEED)
  295.     {
  296.         if (stricmp(tmp, "true") == 0)
  297.             ntauth = 1;
  298.     }
  299.  
  300.     radiusauth = 0;
  301.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_RADIUSAUTH, tmp, 30, 
  302.         (SA_INT *)NULL) == SA_SUCCEED)
  303.     {
  304.         if (stricmp(tmp, "true") == 0)
  305.             radiusauth = 1;
  306.     }
  307.  
  308.     sqlauth = 0;
  309.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_SQLAUTH, tmp, 30, 
  310.         (SA_INT *)NULL) == SA_SUCCEED)
  311.     {
  312.         if (stricmp(tmp, "true") == 0)
  313.             sqlauth = 1;
  314.     }
  315.  
  316.     /* 
  317.     ** REDIRECT
  318.     */
  319.     security = Entries[SECURITY_REDIRECT];
  320.     while (security != (SECURITY *)NULL)
  321.     {
  322.         if ((urilen >= security->namelen) && 
  323.             (strnicmp(uri, security->name, security->namelen) == 0))
  324.         {
  325.             *infop = SA_E_REDIRECT;
  326.             entry = security->entries;
  327.             (SA_VOID)sa_conn_redirect(saconn, entry->value, 
  328.                 "Request redirected.", SA_NULLTERM);
  329.             return (SA_FAIL);
  330.         }
  331.  
  332.         security = security->next;
  333.     }
  334.  
  335.     /*
  336.     ** RESTRICT
  337.     */
  338.     security = Entries[SECURITY_RESTRICT];
  339.     while (security != (SECURITY *)NULL)
  340.     {
  341.         if ((urilen >= security->namelen) && 
  342.             (strnicmp(uri, security->name, security->namelen) == 0))
  343.         {
  344.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_NAME, name, 60,
  345.                 &namelen) != SA_SUCCEED)
  346.             {
  347.                 *infop = SA_E_INVALIDLOGIN;
  348.                 return (SA_FAIL);
  349.             }
  350.  
  351.             /* Get the password and verify the match                    */
  352.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_PASSWORD, pwd, 60,
  353.                 &pwdlen) != SA_SUCCEED)
  354.             {
  355.                 *infop = SA_E_INVALIDLOGIN;
  356.                 return (SA_FAIL);
  357.             }
  358.  
  359.             /* 
  360.             ** Now lookup the name/password in the passwd file or
  361.             ** NT Domain or Radius Server (depending on configuration).
  362.             */
  363.             if ((ntauth) || (radiusauth))
  364.             {
  365.                 if (sa_passwd_verify(sactx, name, namelen, pwd, pwdlen, &status)
  366.                     != SA_SUCCEED)
  367.                 {
  368.                     *infop = SA_E_INVALIDLOGIN;
  369.                     return (SA_FAIL);
  370.                 }
  371.  
  372.                 if (!status)
  373.                 {
  374.                     *infop = SA_E_INVALIDLOGIN;
  375.                     return (SA_FAIL);
  376.                 }
  377.             }
  378.             else if (sqlauth)
  379.             {
  380.                 if (sa_passwd_sqlauth(sactx, saconn, name, namelen, pwd, pwdlen,
  381.                     &passwd) != SA_SUCCEED)
  382.                 {
  383.                     *infop = SA_E_INVALIDLOGIN;
  384.                     return (SA_FAIL);
  385.                 }
  386.             }
  387.             else
  388.             {
  389.                 if (sa_passwd_lookup(sactx, name, namelen, &passwd) 
  390.                     != SA_SUCCEED)
  391.                 {
  392.                     *infop = SA_E_INVALIDLOGIN;
  393.                     return (SA_FAIL);
  394.                 }
  395.  
  396.                 if (pwdlen != passwd.passwordlen)
  397.                 {
  398.                     *infop = SA_E_INVALIDLOGIN;
  399.                     return (SA_FAIL);
  400.                 }
  401.  
  402.                 if ((pwdlen > 0) && 
  403.                     (memcmp(passwd.password, pwd, pwdlen) != 0))
  404.                 {
  405.                     *infop = SA_E_INVALIDLOGIN;
  406.                     return (SA_FAIL);
  407.                 }
  408.             }
  409.  
  410.             /* 
  411.             ** Lastly, verify the security entry(s) match either the name
  412.             ** or group name of the user.
  413.             */
  414.             found = 0;
  415.             entry = security->entries;
  416.             while ((!found) && (entry != (ENTRY *)NULL))
  417.             {
  418.                 /* Match with the username?                                */
  419.                 if ((namelen == entry->valuelen) &&
  420.                      (memcmp(entry->value, name, namelen) == 0))
  421.                 {
  422.                     found = 1;
  423.                     continue;
  424.                 }
  425.  
  426.                 /* Match with the user group?                            */
  427.                 if ((!ntauth) && (!radiusauth) && 
  428.                     (passwd.grouplen == entry->valuelen) &&
  429.                     (memcmp(entry->value, passwd.group, passwd.grouplen) == 0))
  430.                 {
  431.                     found = 1;
  432.                     continue;
  433.                 }
  434.  
  435.                 entry = entry->next;
  436.             }
  437.  
  438.             if (!found)
  439.             {
  440.                 *infop = SA_E_INVALIDLOGIN;
  441.                 return (SA_FAIL);
  442.             }
  443.  
  444.             /*
  445.             ** Finally, if a full "user" should be created (with server-side
  446.             ** state), do so here.
  447.             */
  448.             if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_AUTHLOGINS, tmp, 30,
  449.                 (SA_INT *)NULL) == SA_SUCCEED)
  450.             {
  451.                 if ((strcmp(tmp, "true") == 0) &&
  452.                     (sa_conn_login(saconn, name, namelen, pwd, pwdlen, infop)
  453.                     != SA_SUCCEED))
  454.                 {
  455.                     return (SA_FAIL);
  456.                 }
  457.             }
  458.         }
  459.  
  460.         security = security->next;
  461.     }
  462.     
  463.     /*
  464.     ** DENY
  465.     */
  466.     if ((Entries[SECURITY_DENY] != (SECURITY *)NULL) &&
  467.         (sa_conn_props(saconn, SA_GET, SA_CONNPROP_HOST, name, 60,
  468.         &namelen) == SA_SUCCEED))
  469.     {
  470.         security = Entries[SECURITY_DENY];
  471.         while (security != (SECURITY *)NULL)
  472.         {
  473.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  474.                 name, strlen(name)) == 0)
  475.             {
  476.                 entry = security->entries;
  477.                 *infop = SA_E_REDIRECT;
  478.                 (SA_VOID)sa_conn_redirect(saconn, entry->value, 
  479.                     "Request redirected.", SA_NULLTERM);
  480.                 return (SA_FAIL);
  481.             }
  482.  
  483.             security = security->next;
  484.         }
  485.     }
  486.  
  487.     /*
  488.     ** IP-RESTRICT
  489.     */
  490.     security = Entries[SECURITY_IPRESTRICT];
  491.     while (security != (SECURITY *)NULL)
  492.     {
  493.         if ((urilen >= security->namelen) && 
  494.             (strnicmp(uri, security->name, security->namelen) == 0))
  495.         {
  496.             /* Get the IP address of the client.                        */
  497.             if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_IPADDR, name, 60,
  498.                 &namelen) != SA_SUCCEED)
  499.             {
  500.                 return (SA_FAIL);
  501.             }
  502.  
  503.             /* 
  504.             ** Lastly, verify the security entry(s) match the IP
  505.             ** address of the client.
  506.             */
  507.             found = 0;
  508.             entry = security->entries;
  509.             while ((!found) && (entry != (ENTRY *)NULL))
  510.             {
  511.                 if (sa_wildcmp(sactx, entry->value, entry->valuelen, 
  512.                     name, namelen) == 0)
  513.                 {
  514.                     found = 1;
  515.                     continue;
  516.                 }
  517.  
  518.                 entry = entry->next;
  519.             }
  520.  
  521.             if (!found)
  522.             {
  523.                 *infop = SA_E_FORBIDDEN;
  524.                 return (SA_FAIL);
  525.             }
  526.         }
  527.  
  528.         security = security->next;
  529.     }
  530.     
  531.     /* 
  532.     ** HOSTREDIRECT
  533.     */
  534.     security = Entries[SECURITY_HOSTREDIRECT];
  535.     if ((security != (SECURITY *)NULL) &&
  536.         (sa_conn_props(saconn, SA_GET, SA_CONNPROP_REQUESTHOST, name, 60,
  537.         &namelen) == SA_SUCCEED))
  538.     {
  539.         while (security != (SECURITY *)NULL)
  540.         {
  541.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  542.                 name, namelen) == 0)
  543.             {
  544.                 entry = security->entries;
  545.                 *infop = SA_E_REDIRECT;
  546.                 (SA_VOID)sa_conn_redirect(saconn, entry->value, 
  547.                     "Request redirected.", SA_NULLTERM);
  548.                 return (SA_FAIL);
  549.             }
  550.  
  551.             security = security->next;
  552.         }
  553.     }
  554.  
  555.     /* 
  556.     ** SITEREDIRECT
  557.     */
  558.     security = Entries[SECURITY_SITEREDIRECT];
  559.     if ((security != (SECURITY *)NULL) &&
  560.         (sa_conn_props(saconn, SA_GET, SA_CONNPROP_REQUESTHOST, name, 60,
  561.         &namelen) == SA_SUCCEED))
  562.     {
  563.         while (security != (SECURITY *)NULL)
  564.         {
  565.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  566.                 name, namelen) == 0)
  567.             {
  568.                 if (sa_conn_props(saconn, SA_GET, SA_CONNPROP_URL, name, 
  569.                     500, &namelen) != SA_SUCCEED)
  570.                 {
  571.                     return (SA_FAIL);
  572.                 }
  573.  
  574.                 entry = security->entries;
  575.                 if (namelen + strlen(entry->value) > 1000)
  576.                     return (SA_FAIL);
  577.  
  578.                 *infop = SA_E_REDIRECT;
  579.                 sprintf(tmp, "%s%s", entry->value, name);
  580.                 (SA_VOID)sa_conn_redirect(saconn, tmp,
  581.                     "Request redirected.", SA_NULLTERM);
  582.                 return (SA_FAIL);
  583.             }
  584.  
  585.             security = security->next;
  586.         }
  587.     }
  588.  
  589.     return (SA_SUCCEED);
  590. }
  591.  
  592. /*
  593. **  SECURITY_CONNECT
  594. **
  595. **    Determine if the connection should be allowed.
  596. **
  597. **  Parameters:
  598. **    sactx        Sambar Server context
  599. **    ipaddr        The IP address of the client requesting a connection.
  600. **    servertype    The server the client is attempting to connect to.
  601. **
  602. **  Returns:
  603. **    SA_SUCCEED | SA_FAIL
  604. */
  605. SA_RETCODE SA_PUBLIC
  606. security_connect(sactx, ipaddr, servertype)
  607. SA_CTX        *sactx;
  608. SA_CHAR        *ipaddr;
  609. SA_INT        servertype;
  610. {
  611.     SA_INT        denyid;
  612.     SA_INT        acceptid;
  613.     SA_INT        ipaddrlen;
  614.     SA_BOOL        found;
  615.     SA_CHAR        *server;
  616.     SA_CHAR        *desc;
  617.     SECURITY    *security;
  618.     SA_CHAR        buffer[512];
  619.  
  620.     /* Initialization                                                    */
  621.     ipaddrlen = strlen(ipaddr);
  622.  
  623.     switch((int)servertype)
  624.     {
  625.     case SA_SERVERTYPE_HTTP:
  626.         server = "HTTP";
  627.         denyid = SECURITY_HTTPDENY;
  628.         acceptid = SECURITY_HTTPACCEPT;
  629.         break;
  630.  
  631.     case SA_SERVERTYPE_FTP:
  632.         server = "FTP";
  633.         denyid = SECURITY_FTPDENY;
  634.         acceptid = SECURITY_FTPACCEPT;
  635.         break;
  636.  
  637.     case SA_SERVERTYPE_HTTPPROXY:
  638.     case SA_SERVERTYPE_SMTPPROXY:
  639.     case SA_SERVERTYPE_POP3PROXY:
  640.     case SA_SERVERTYPE_IMAP4PROXY:
  641.     case SA_SERVERTYPE_BRIDGEPROXY:
  642.     case SA_SERVERTYPE_NNTPPROXY:
  643.     case SA_SERVERTYPE_FTPPROXY:
  644.     case SA_SERVERTYPE_SOCKSPROXY:
  645.     case SA_SERVERTYPE_TELNETPROXY:
  646.     case SA_SERVERTYPE_REALPROXY:
  647.     case SA_SERVERTYPE_TCPPROXY:
  648.     case SA_SERVERTYPE_UDPPROXY:
  649.         server = "PROXY";
  650.         denyid = SECURITY_PROXYDENY;
  651.         acceptid = SECURITY_PROXYACCEPT;
  652.         break;
  653.  
  654.     case SA_SERVERTYPE_SMTP:
  655.     case SA_SERVERTYPE_POP3:
  656.     case SA_SERVERTYPE_IMAP4:
  657.         server = "Mail";
  658.         denyid = SECURITY_MAILDENY;
  659.         acceptid = SECURITY_MAILACCEPT;
  660.         break;
  661.  
  662.     case SA_SERVERTYPE_DNS:
  663.         server = "DNS";
  664.         denyid = SECURITY_DNSDENY;
  665.         acceptid = SECURITY_DNSACCEPT;
  666.         break;
  667.  
  668.     case SA_SERVERTYPE_SIP:
  669.         server = "SIP";
  670.         denyid = SECURITY_SIPDENY;
  671.         acceptid = SECURITY_SIPACCEPT;
  672.         break;
  673.  
  674.     case SA_SERVERTYPE_TFTP:
  675.         server = "TFTP";
  676.         denyid = SECURITY_TFTPDENY;
  677.         acceptid = SECURITY_TFTPACCEPT;
  678.         break;
  679.  
  680.     default:
  681.         sprintf(buffer, "NETCONNECT: Unrecognized server (%ld)", servertype);
  682.         sa_log2(sactx, SA_LOG_ERROR, buffer);
  683.         return (SA_FAIL);
  684.     }
  685.  
  686.     /* 
  687.     ** NETACCEPT
  688.     **
  689.     ** The client must be in the accept list.
  690.     */
  691.     found = 0;
  692.     security = Entries[acceptid];
  693.     while ((!found) && (security != (SECURITY *)NULL))
  694.     {
  695.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  696.             ipaddr, ipaddrlen) == 0)
  697.         {
  698.             found = 1;
  699.             continue;
  700.         }
  701.  
  702.         security = security->next;
  703.     }
  704.  
  705.     if (!found)
  706.     {
  707.         sprintf(buffer, 
  708.             "NETCONNECT: Client %s not in accept list for server %s.",
  709.             ipaddr, server);
  710.         sa_log2(sactx, SA_LOG_WARN, buffer);
  711.         return (SA_FAIL);
  712.     }
  713.  
  714.     /* 
  715.     ** NETDENY
  716.     **
  717.     ** The client cannot be in the deny list.
  718.     */
  719.     security = Entries[denyid];
  720.     while (security != (SECURITY *)NULL)
  721.     {
  722.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  723.             ipaddr, ipaddrlen) == 0)
  724.         {
  725.             desc = "unknown";
  726.             if (security->entries != (ENTRY *)NULL)
  727.                 desc = security->entries->value;
  728.  
  729.             sprintf(buffer, 
  730.                 "NETCONNECT: Client %s is in deny list for server %s [%s].", 
  731.                 ipaddr, server, desc);
  732.             sa_log2(sactx, SA_LOG_WARN, buffer);
  733.             return (SA_FAIL);
  734.         }
  735.  
  736.         security = security->next;
  737.     }
  738.  
  739.     return (SA_SUCCEED);
  740. }
  741.  
  742. /*
  743. **  SECURITY_FILTER
  744. **
  745. **    Filter all HTTP Proxy requests.
  746. **
  747. **  If the requested URL is found in the [httpfilter] section, either 
  748. **    return the file specified in the file in response to the request, 
  749. **    or return a 404 request denied message if no file is specified.
  750. **
  751. **  If the requested URL is NOT found in the [httprestrict] section, 
  752. **    return a 404 request denied message.
  753. **
  754. **  If the requested URL is found in the [urlfilter] section, 
  755. **    return a 404 request denied message.
  756. **
  757. **
  758. **  Parameters:
  759. **    sactx        Sambar Server context
  760. **
  761. **  Returns:
  762. **    SA_SUCCEED | SA_FAIL
  763. */
  764. SA_RETCODE SA_PUBLIC
  765. security_filter(sactx, saconn, host, hostlen, url, urllen)
  766. SA_CTX        *sactx;
  767. SA_CONN        *saconn;
  768. SA_CHAR        *host;
  769. SA_INT        hostlen;
  770. SA_CHAR        *url;
  771. SA_INT        urllen;
  772. {
  773.     SA_INT        i;
  774.     SA_INT        len;
  775.     SA_INT        urlcaselen;
  776.     SA_BOOL        found;
  777.     ENTRY        *entry;
  778.     SECURITY    *security;
  779.     SA_CHAR        urlcase[1024];
  780.     SA_CHAR        buffer[2048];
  781.  
  782.     /*
  783.     ** Convert the host and URL to lower case.
  784.     */
  785.     for (i = 0; i < hostlen; i++)
  786.         host[i] = tolower(host[i]);
  787.  
  788.     urlcaselen = 0;
  789.     while ((urlcaselen < urllen) && (urlcaselen < 1000))
  790.     {
  791.         urlcase[urlcaselen] = tolower(url[urlcaselen]);
  792.         urlcaselen++;
  793.     }
  794.  
  795.     urlcase[urlcaselen] = '\0';
  796.  
  797.     security = Entries[SECURITY_HOSTFILTER];
  798.     while (security != (SECURITY *)NULL)
  799.     {
  800.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  801.             host, hostlen) == 0)
  802.         {
  803.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  804.             if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, buffer,
  805.                 1000, &len) == SA_SUCCEED)
  806.             {
  807.                 strcat(buffer, "\\messages\\filtered.htm");
  808.                 (SA_VOID)sa_send_file(saconn, buffer);
  809.             }
  810.  
  811.             entry = security->entries;
  812.             if ((entry != (ENTRY *)NULL) &&
  813.                 (hostlen + entry->valuelen < 1000))
  814.             {
  815.                 sprintf(buffer, "HTTPPROXY: Host %s blocked by filter: %s", 
  816.                     host, entry->value);
  817.                 sa_log2(sactx, SA_LOG_WARN, buffer);
  818.             }
  819.  
  820.             return (SA_FAIL);
  821.         }
  822.  
  823.         security = security->next;
  824.     }
  825.  
  826.     security = Entries[SECURITY_URLFILTER];
  827.     while (security != (SECURITY *)NULL)
  828.     {
  829.         if (sa_wildcmp(sactx, security->name, security->namelen, 
  830.             urlcase, urlcaselen) == 0)
  831.         {
  832.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  833.             if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, buffer,
  834.                 1000, &len) == SA_SUCCEED)
  835.             {
  836.                 strcat(buffer, "\\messages\\filtered.htm");
  837.                 (SA_VOID)sa_send_file(saconn, buffer);
  838.             }
  839.  
  840.             entry = security->entries;
  841.             if ((entry != (ENTRY *)NULL) &&
  842.                 (urlcaselen + entry->valuelen < 900))
  843.             {
  844.                 sprintf(buffer, "HTTPPROXY: URL blocked by filter '%s' : ",
  845.                     entry->value); 
  846.                 strcat(buffer, urlcase);
  847.                 sa_log2(sactx, SA_LOG_WARN, buffer);
  848.             }
  849.  
  850.             return (SA_FAIL);
  851.         }
  852.  
  853.         security = security->next;
  854.     }
  855.  
  856.     /* 
  857.     ** If a [hostrestrict] entry is found, the host must match 
  858.     ** an entry on the list provided or it will be denied.
  859.     */
  860.     security = Entries[SECURITY_HOSTRESTRICT];
  861.     if (security != (SECURITY *)NULL)
  862.     {
  863.         found = 0;
  864.         while ((!found) && (security != (SECURITY *)NULL))
  865.         {
  866.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  867.                 host, hostlen) == 0)
  868.             {
  869.                 found = 1;
  870.                 continue;
  871.             }
  872.  
  873.             security = security->next;
  874.         }
  875.  
  876.         if (!found)
  877.         {
  878.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  879.             if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, buffer,
  880.                 1000, &len) == SA_SUCCEED)
  881.             {
  882.                 strcat(buffer, "\\messages\\filtered.htm");
  883.                 (SA_VOID)sa_send_file(saconn, buffer);
  884.             }
  885.             else
  886.             {
  887.                 sprintf(buffer, 
  888.                     "<!-- HTTPPROXY: Host '%s' not on [hostrestrict] list -->", 
  889.                     host);
  890.                 (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  891.             }
  892.  
  893.             sprintf(buffer, "HTTPPROXY: Host '%s' not on [hostrestrict] list", 
  894.                     host);
  895.             sa_log2(sactx, SA_LOG_WARN, buffer);
  896.             return (SA_FAIL);
  897.         }
  898.     }
  899.  
  900.     /* 
  901.     ** If a [urlrestrict] entry is found, the URL must match 
  902.     ** an entry on the list provided or it will be denied.
  903.     */
  904.     security = Entries[SECURITY_URLRESTRICT];
  905.     if (security != (SECURITY *)NULL)
  906.     {
  907.         found = 0;
  908.         while ((!found) && (security != (SECURITY *)NULL))
  909.         {
  910.             if (sa_wildcmp(sactx, security->name, security->namelen, 
  911.                 urlcase, urlcaselen) == 0)
  912.             {
  913.                 found = 1;
  914.                 continue;
  915.             }
  916.  
  917.             security = security->next;
  918.         }
  919.  
  920.         if (!found)
  921.         {
  922.             (SA_VOID)sa_send_header(saconn, DENIED_HEADER, SA_NULLTERM);
  923.             if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_HOMEDIR, buffer,
  924.                 1000, &len) == SA_SUCCEED)
  925.             {
  926.                 strcat(buffer, "\\messages\\filtered.htm");
  927.                 (SA_VOID)sa_send_file(saconn, buffer);
  928.             }
  929.             else
  930.             {
  931.                 strcpy(buffer, 
  932.                     "<!-- HTTPPROXY: URL not on [urlrestrict] list : ");
  933.                 strcat(buffer, urlcase);
  934.                 strcat(buffer, " -->");
  935.                 (SA_VOID)sa_conn_send(saconn, buffer, SA_NULLTERM);
  936.             }
  937.  
  938.             strcpy(buffer, "HTTPPROXY: URL not on [urlrestrict] list : ");
  939.             strcat(buffer, urlcase);
  940.             sa_log2(sactx, SA_LOG_WARN, buffer);
  941.             return (SA_FAIL);
  942.         }
  943.     }
  944.  
  945.     /* HTTP Request should be allowed through.                            */
  946.     return (SA_SUCCEED);
  947. }
  948.  
  949. /*
  950. **  SECURITY__LOAD
  951. **
  952. **    Load a single security rule.
  953. **
  954. **  Parameters:
  955. **    sactx        Sambar Server context
  956. **    argp        Security parameter.
  957. **    name        Left hand argument.
  958. **    value        Right hand argument.
  959. **
  960. **  Returns:
  961. **    SA_SUCCEED | SA_FAIL
  962. */
  963. SA_RETCODE
  964. security__load(sactx, argp, name, value)
  965. SA_CTX        *sactx;
  966. SA_VOID        *argp;
  967. SA_CHAR        *name;
  968. SA_CHAR        *value;
  969. {
  970.     SA_INT        pos;
  971.     SA_INT        head;
  972.     SA_INT        valuelen;
  973.     ENTRY        *entry;
  974.     SECURITY    *security;
  975.  
  976.     security = (SECURITY *)malloc(sizeof(SECURITY));
  977.     if (security == (SECURITY *)NULL)
  978.         return (SA_FAIL);
  979.  
  980.     memset(security, 0, sizeof(SECURITY));
  981.     security->namelen = strlen(name);
  982.     valuelen = strlen(value);
  983.  
  984.     if (security->namelen == 0) 
  985.         return (SA_FAIL);
  986.  
  987.     /* Is a value required?                                                */
  988.     if ((valuelen == 0) &&
  989.         (*(SA_INT *)argp != SECURITY_DENY) &&
  990.         (*(SA_INT *)argp != SECURITY_HTTPACCEPT) &&
  991.         (*(SA_INT *)argp != SECURITY_HTTPDENY) &&
  992.         (*(SA_INT *)argp != SECURITY_FTPACCEPT) &&
  993.         (*(SA_INT *)argp != SECURITY_FTPDENY) &&
  994.         (*(SA_INT *)argp != SECURITY_MAILACCEPT) &&
  995.         (*(SA_INT *)argp != SECURITY_MAILDENY) &&
  996.         (*(SA_INT *)argp != SECURITY_DNSACCEPT) &&
  997.         (*(SA_INT *)argp != SECURITY_DNSDENY) &&
  998.         (*(SA_INT *)argp != SECURITY_SIPACCEPT) &&
  999.         (*(SA_INT *)argp != SECURITY_SIPDENY) &&
  1000.         (*(SA_INT *)argp != SECURITY_TFTPACCEPT) &&
  1001.         (*(SA_INT *)argp != SECURITY_TFTPDENY) &&
  1002.         (*(SA_INT *)argp != SECURITY_HOSTFILTER) &&
  1003.         (*(SA_INT *)argp != SECURITY_IPRESTRICT) &&
  1004.         (*(SA_INT *)argp != SECURITY_URLRESTRICT) &&
  1005.         (*(SA_INT *)argp != SECURITY_URLFILTER))
  1006.     {
  1007.         return (SA_FAIL);
  1008.     }
  1009.  
  1010.     security->name = strdup(name);
  1011.  
  1012.     /* Restriction & IP-restriction lists have multiple entries            */
  1013.     if ((*(SA_INT *)argp == SECURITY_RESTRICT) ||
  1014.         (*(SA_INT *)argp == SECURITY_IPRESTRICT))
  1015.     {
  1016.         pos = 0;
  1017.         while (pos < valuelen)
  1018.         {
  1019.             head = pos;
  1020.             while ((pos < valuelen) && !isspace(value[pos]))
  1021.                 pos++;
  1022.  
  1023.             value[pos] = '\0';
  1024.  
  1025.             entry = (ENTRY *)malloc(sizeof(ENTRY));
  1026.             if (entry == (ENTRY *)NULL)
  1027.                 return (SA_FAIL);
  1028.  
  1029.             memset(entry, 0, sizeof(ENTRY));
  1030.             entry->value = strdup(&value[head]);
  1031.             entry->valuelen = pos - head;;
  1032.             entry->next = security->entries;
  1033.             security->entries = entry;
  1034.  
  1035.             pos++;
  1036.             while ((pos < valuelen) && isspace(value[pos]))
  1037.                 pos++;
  1038.         }
  1039.     }
  1040.     else
  1041.     {
  1042.         entry = (ENTRY *)malloc(sizeof(ENTRY));
  1043.         if (entry == (ENTRY *)NULL)
  1044.             return (SA_FAIL);
  1045.  
  1046.         memset(entry, 0, sizeof(ENTRY));
  1047.         entry->valuelen = valuelen;
  1048.         entry->value = strdup(value);
  1049.         security->entries = entry;
  1050.     }
  1051.  
  1052.     security->next = TmpEntries[*(SA_INT *)argp];
  1053.     TmpEntries[*(SA_INT *)argp] = security;
  1054.  
  1055.     return (SA_SUCCEED);
  1056. }
  1057.  
  1058. /*
  1059. **  SECURITY_SHOWSEC
  1060. **
  1061. **    Show the security associated with a particular symbol.
  1062. **
  1063. **  Parameters:
  1064. **    sactx        Sambar Server context
  1065. **    saconn        Sambar Server connection
  1066. **    saparams    RPC Parameters
  1067. **    infop        Error parameters
  1068. **
  1069. **  Returns:
  1070. **    SA_SUCCEED | SA_FAIL
  1071. */
  1072. SA_RETCODE SA_PUBLIC
  1073. security_showsec(sactx, saconn, saparams, infop)
  1074. SA_CTX        *sactx;
  1075. SA_CONN        *saconn;
  1076. SA_PARAMS    *saparams;
  1077. SA_INT        *infop;
  1078. {
  1079.     SA_INT        i;
  1080.     SA_BOOL        found;
  1081.     SA_INT        datalen;
  1082.     SA_CHAR        *data;
  1083.     ENTRY        *entry;
  1084.     SECURITY    *security;
  1085.     SA_CHAR        buffer[1024];
  1086.  
  1087.     if ((sa_param(sactx, saparams, "type", &data, &datalen) != SA_SUCCEED) 
  1088.         || (datalen == 0) || (datalen > 64))
  1089.     {
  1090.         /* No report type given                                            */
  1091.         return (SA_SUCCEED);
  1092.     }
  1093.  
  1094.     i = 0;
  1095.     found = 0;
  1096.     while ((i < NUM_ENTRIES) && (!found))
  1097.     {
  1098.         if (strcmp(Security_entries[i].symbol, (SA_CHAR *)data) == 0)
  1099.             found = 1;
  1100.         else
  1101.             i++;
  1102.     }
  1103.  
  1104.     if (!found)
  1105.     {
  1106.         *infop = SA_E_INVALIDDATA;
  1107.         return (SA_FAIL);
  1108.     }
  1109.  
  1110.     sprintf(buffer, "<FONT SIZE=+1><B>%s</B></FONT><P>\n", 
  1111.         Security_entries[i].descr);
  1112.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1113.         return (SA_FAIL);
  1114.  
  1115.     security = Entries[i];
  1116.     if (security == (SECURITY *)NULL)
  1117.     {
  1118.         if (sa_conn_send(saconn, "<I>No Security Controls defined.", 
  1119.             SA_NULLTERM) != SA_SUCCEED)
  1120.         {
  1121.             return (SA_FAIL);
  1122.         }
  1123.  
  1124.         return (SA_SUCCEED);
  1125.     }
  1126.  
  1127.     if (sa_conn_send(saconn, "<TABLE border=1 cellspacing=4>\n", SA_NULLTERM) 
  1128.         != SA_SUCCEED)
  1129.     {
  1130.         return (SA_FAIL);
  1131.     }
  1132.  
  1133.     while (security != (SECURITY *)NULL)
  1134.     {
  1135.         sprintf(buffer, "<TR><TD>%s</TD><TD>", security->name);
  1136.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1137.             return (SA_FAIL);
  1138.  
  1139.         entry = security->entries;
  1140.         while (entry != (ENTRY *)NULL)
  1141.         {
  1142.             sprintf(buffer, "%s ", entry->value);
  1143.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1144.                 return (SA_FAIL);
  1145.  
  1146.             entry = entry->next;
  1147.         }
  1148.  
  1149.         if (sa_conn_send(saconn, "</TD></TR>\n", SA_NULLTERM) != SA_SUCCEED)
  1150.             return (SA_FAIL);
  1151.  
  1152.         security = security->next;
  1153.     }
  1154.  
  1155.     if (sa_conn_send(saconn, "</TABLE>\n", SA_NULLTERM) != SA_SUCCEED)
  1156.         return (SA_FAIL);
  1157.  
  1158.     return (SA_SUCCEED);
  1159. }
  1160.  
  1161. /*
  1162. **  SECURITY_RELOAD
  1163. **
  1164. **    Reload the security rules.
  1165. **    Note: The final step (swapping security rules) should be mutexed.
  1166. **    It results in a memory leak and could lead to request failure.
  1167. **
  1168. **  Parameters:
  1169. **    sactx        Sambar Server context
  1170. **    saconn        Sambar Server connection
  1171. **    saparams    RPC Parameters
  1172. **    infop        Error parameters
  1173. **
  1174. **  Returns:
  1175. **    SA_SUCCEED | SA_FAIL
  1176. */
  1177. SA_RETCODE SA_PUBLIC
  1178. security_reload(sactx, saconn, saparams, infop)
  1179. SA_CTX        *sactx;
  1180. SA_CONN        *saconn;
  1181. SA_PARAMS    *saparams;
  1182. SA_INT        *infop;
  1183. {
  1184.     SA_INT    i;
  1185.     SA_CHAR    buffer[255];
  1186.  
  1187.     for (i = 0; i < NUM_ENTRIES; i++)
  1188.     {
  1189.         TmpEntries[i] = (SECURITY *)NULL;
  1190.  
  1191.         if (sa_props_load(sactx, "security.ini", 
  1192.             Security_entries[i].symbol, &Security_entries[i].id, 
  1193.             (SA_PROPFUNC)security__load) != SA_SUCCEED)
  1194.         {
  1195.             sprintf(buffer, "Failure loading [%s] security section.", 
  1196.                 Security_entries[i].symbol);
  1197.             sa_log2(sactx, SA_LOG_ERROR, buffer);
  1198.             *infop = SA_E_INTERNALSYSTEM;
  1199.             return (SA_FAIL);
  1200.         }
  1201.     }
  1202.  
  1203.     /* Swap the security rules (leaks memory)                            */
  1204.     for (i = 0; i < NUM_ENTRIES; i++)
  1205.         Entries[i] = TmpEntries[i];
  1206.  
  1207.     return (SA_SUCCEED);
  1208. }
  1209.