home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 April / PCWorld_2000-04_cd.bin / Komunik / Servery / sambar / _setup.1 / login.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-09  |  45.2 KB  |  1,813 lines

  1. /*
  2. ** LOGIN
  3. **
  4. **      HTTP Wrapper for the Login/Logout/Profile Management Library
  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. **        login_init
  14. **        user_login
  15. **        user_logout
  16. **        user_profile
  17. **        user_add
  18. **        user_delete
  19. **        user_update
  20. **        user_passwd
  21. **        user_list
  22. **        user_select
  23. **        user_maillist
  24. **        user_mailbox
  25. **        group_add
  26. **        group_delete
  27. **        group_list
  28. **        group_select
  29. **        ftp_connect
  30. **        mail_connect
  31. **        telnet_connect
  32. **
  33. **
  34. ** History:
  35. ** Chg#    Date    Description                                                Resp
  36. ** ----    -------    -------------------------------------------------------    ----
  37. **         27JAN96    Created                                                    sambar
  38. **         29MAR97    Added user list and update functions                    sambar
  39. **         30MAR97    Added FTP connection security                            sambar
  40. **         10OCT97    Added user password interface                            sambar
  41. **        14NOV97 Added group management                                    sambar
  42. **         28OCT98    Added MAIL connection security                            sambar
  43. */
  44.  
  45. #include    <stdio.h>
  46. #include    <stdlib.h>
  47. #include    <memory.h>
  48. #include    <string.h>
  49. #include    <login.h>
  50.  
  51. /*
  52. ** Login RPC Commands
  53. */
  54. typedef struct login__rpcs
  55. {
  56.     SA_CHAR        *name;
  57.     SA_RPCPARAM    *params;
  58.     SA_INT        numparams;
  59.     SA_INT        auth;
  60.     SA_VOID        *func;
  61.     SA_CHAR        *descr;
  62. } LOGIN__RPCS;
  63.  
  64. static SA_RPCPARAM    adduserp [] =
  65. {
  66.     { "username",     1,    "User login." },
  67.     { "password",     0,    "User password." },
  68.     { "group",         0,    "User group." },
  69.     { "name",         0,    "User name." },
  70.     { "dir",         0,    "Ftp directory of the user." },
  71.     { "ftpprivs",     1,    "FTP priviledges of the user." },
  72.     { "ftpmax",     1,    "FTP maximum upload (MB)." },
  73.     { "mbox",         0,    "Create a mailbox for the user." }
  74. };
  75. static SA_RPCPARAM    upduserp [] =
  76. {
  77.     { "username",     1,    "User login." },
  78.     { "password",     0,    "User password." },
  79.     { "group",         0,    "User group." },
  80.     { "name",         0,    "User name." },
  81.     { "dir",         0,    "Ftp directory of the user." },
  82.     { "ftpprivs",     1,    "FTP priviledges of the user." },
  83.     { "ftpmax",     1,    "FTP maximum upload (MB)." },
  84.     { "mbox",         0,    "Create a mailbox for the user." }
  85. };
  86. static SA_RPCPARAM    deluserp [] =
  87. {
  88.     { "username",     1,    "User login." }
  89. };
  90. static SA_RPCPARAM    userpropp [] =
  91. {
  92.     { "username",     1,    "User login." },
  93.     { "prop",     1,    "User property: group,password,name,dir,ftpprivs,ftpmax" }
  94. };
  95. static SA_RPCPARAM    selectuserp [] =
  96. {
  97.     { "username",     0,    "User login." },
  98. };
  99. static SA_RPCPARAM    addgroupp [] =
  100. {
  101.     { "groupname",     1,    "Symbolic name of the group." }
  102. };
  103. static SA_RPCPARAM    delgroupp [] =
  104. {
  105.     { "groupname",     1,    "Symbolic name of the group." }
  106. };
  107. static SA_RPCPARAM    selectgroupp [] =
  108. {
  109.     { "username",     0,    "User to test against group list." }
  110. };
  111. static SA_RPCPARAM    userpasswdp [] =
  112. {
  113.     { "username",     1,    "User login." },
  114.     { "password",     0,    "Existing password for the user." },
  115.     { "newpasswd",     0,    "New password for the user." },
  116.     { "confpasswd",    0,    "Confirm new password." }
  117. };
  118. static SA_RPCPARAM    usermboxp [] =
  119. {
  120.     { "username",     1,    "User login." },
  121.     { "action",     1,    "Create/Delete user mailbox." }
  122. };
  123.  
  124. static LOGIN__RPCS        login_rpcs [] =
  125. {
  126.     { "adduser",     adduserp,    sizeof(adduserp)/sizeof(SA_RPCPARAM),
  127.        SA_AUTHORIZATION_ADMIN,    (SA_VOID *)user_add,
  128.       "Add a user to the system." },
  129.     { "upduser",     upduserp,    sizeof(upduserp)/sizeof(SA_RPCPARAM),    
  130.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_update,
  131.       "Update a user." }, 
  132.     { "deluser",    deluserp,    sizeof(deluserp)/sizeof(SA_RPCPARAM),     
  133.        SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_delete,
  134.       "Delete a user from the system." },
  135.     { "userprop",    userpropp,    sizeof(userpropp)/sizeof(SA_RPCPARAM),     
  136.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_prop,
  137.       "Get a single user attribute for display." },
  138.     { "listusers",    NULL, 0,
  139.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_list,
  140.       "List users for update/delete." },
  141.     { "selectuser",    selectuserp,sizeof(selectuserp)/sizeof(SA_RPCPARAM),    
  142.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_select,
  143.       "List users for selection in a pick list." },
  144.     { "mailusers",    NULL, 0,
  145.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_maillist,
  146.       "List mail users for update/delete." },
  147.     { "usermbox",    usermboxp,    sizeof(usermboxp)/sizeof(SA_RPCPARAM),    
  148.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)user_mailbox,
  149.       "Create/Delete a user mailbox." },
  150.  
  151.     { "addgroup",    addgroupp,    sizeof(addgroupp)/sizeof(SA_RPCPARAM),     
  152.       SA_AUTHORIZATION_ADMIN,    (SA_VOID *)group_add,
  153.       "Add a group to the system." },
  154.     { "delgroup",     delgroupp,    sizeof(delgroupp)/sizeof(SA_RPCPARAM),    
  155.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)group_delete,
  156.       "Delete a group from the system." },
  157.     { "listgroups",    NULL, 0,
  158.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)group_list,
  159.       "List groups for delete." },
  160.     { "selectgroup",selectgroupp,    sizeof(selectgroupp)/sizeof(SA_RPCPARAM),
  161.       SA_AUTHORIZATION_ADMIN,     (SA_VOID *)group_select,
  162.       "List groups for selection in a pick list." },
  163.  
  164.     { "userpasswd",    userpasswdp,    sizeof(userpasswdp)/sizeof(SA_RPCPARAM),    
  165.       SA_AUTHORIZATION_ALL,        (SA_VOID *)user_passwd,
  166.       "Interface to allow users to change their password." }
  167. };
  168.  
  169. /*
  170. **  LOGIN_INIT
  171. **
  172. **    Initialize the Login/Logout/Profile Interfaces for use by the 
  173. **    Sambar Server plugins.
  174. **
  175. **
  176. **  Parameters:
  177. **    sactx        Sambar Server context
  178. **
  179. **  Returns:
  180. **    SA_SUCCEED | SA_FAIL
  181. */
  182. SA_RETCODE SA_PUBLIC
  183. login_init(sactx)
  184. SA_CTX        *sactx;
  185. {
  186.     int        i;
  187.  
  188.     /* Register the User RPCs with the server                            */
  189.     for (i = 0; i < sizeof(login_rpcs) / sizeof(LOGIN__RPCS); i++)
  190.     {
  191.         if (sa_cmd_init(sactx, login_rpcs[i].name, login_rpcs[i].params, 
  192.             login_rpcs[i].numparams, login_rpcs[i].auth, login_rpcs[i].descr,
  193.             (SA_RPCFUNC)login_rpcs[i].func) != SA_SUCCEED)
  194.         {
  195.             sa_log(sactx, "Unable to initialize User Management RPCs");
  196.             return (SA_FAIL);
  197.         } 
  198.     }
  199.  
  200.     sa_log(sactx, "Login/Logout/Profile Management Initialized");
  201.  
  202.     return (SA_SUCCEED);
  203. }
  204.  
  205. /*
  206. **  USER_LOGIN
  207. **
  208. **    Login a user.  Verify the username/password against the Sambar Server
  209. **    password interfaces.  Store some profile information for use.
  210. **
  211. **  Parameters:
  212. **    sactx            Sambar Server Application context to release.
  213. **    saconn            Sambar Server User Connection handle.
  214. **    username        Name of the user logging in.
  215. **    usernamelen        Length of the user name
  216. **    password        Password of the user logging in.
  217. **    passwordlen        Length of the password.
  218. **    infop            Error return code
  219. **
  220. **  Return Values:
  221. **    SA_SUCCESS | SA_FAIL
  222. */
  223. SA_RETCODE SA_PUBLIC
  224. user_login(sactx, saconn, username, usernamelen, password, passwordlen, infop)
  225. SA_CTX        *sactx;
  226. SA_CONN        *saconn;
  227. SA_CHAR        *username;
  228. SA_INT        usernamelen;
  229. SA_CHAR        *password;
  230. SA_INT        passwordlen;
  231. SA_INT        *infop;
  232. {
  233.     SA_INT                namelen;
  234.     SA_PASSWD            passwd;
  235.     LOGIN_PROFILE        *profile;
  236.     SA_CHAR                name[62];
  237.     SA_CHAR                buffer[512];
  238.  
  239.     if (sa_passwd_lookup(sactx, username, usernamelen, &passwd) != SA_SUCCEED)
  240.     {
  241.         (SA_VOID)sa_conn_props(saconn, SA_GET, SA_CONNPROP_HOST, name, 60,
  242.             &namelen);
  243.         name[namelen] = '\0';
  244.         sprintf(buffer, "Login for user '%s' failed [host %s]", username, name);
  245.         sa_log(sactx, buffer);
  246.         *infop = SA_E_INVALIDLOGIN;
  247.         return (SA_FAIL);
  248.     }
  249.  
  250.     /* Verify the passwords are the same                                */
  251.     if ((passwd.passwordlen != passwordlen) ||
  252.         (strncmp(passwd.password, password, passwordlen) != 0))
  253.     {
  254.         (SA_VOID)sa_conn_props(saconn, SA_GET, SA_CONNPROP_HOST, name, 60,
  255.             &namelen);
  256.         name[namelen] = '\0';
  257.         sprintf(buffer, 
  258.             "Login for user '%s' failed - bad password (%s) [host %s]",
  259.             username, password, name);
  260.         sa_log(sactx, buffer);
  261.         *infop = SA_E_INVALIDLOGIN;
  262.         return (SA_FAIL);
  263.     }
  264.  
  265.     /* Allocate and populate a user profile structure                    */
  266.     profile = (LOGIN_PROFILE *)malloc(sizeof(LOGIN_PROFILE));
  267.     if (profile == (LOGIN_PROFILE *)NULL)
  268.     {
  269.         sprintf(buffer, "Login for user '%s' failed - no memory", username);
  270.         sa_log(sactx, buffer);
  271.         *infop = SA_E_INVALIDLOGIN;
  272.         return (SA_FAIL);
  273.     }
  274.  
  275.     if (passwd.namelen > 0)
  276.         memcpy(profile->name, passwd.name, passwd.namelen);
  277.     if (passwd.grouplen > 0)
  278.         memcpy(profile->group, passwd.group, passwd.grouplen);
  279.  
  280.     memcpy(profile->username, username, usernamelen);
  281.  
  282.     profile->name[passwd.namelen] = '\0';
  283.     profile->group[passwd.grouplen] = '\0';
  284.     profile->username[usernamelen] = '\0';
  285.  
  286.     /* Save the user's profile handle with the user connection            */
  287.     if (sa_conn_key(saconn, SA_SET, LOGIN_PROFILE_KEY, (SA_VOID **)profile)
  288.         != SA_SUCCEED)
  289.     {
  290.         (SA_VOID)free(profile);
  291.         sa_log(sactx, "sa_conn_key(SET, LOGIN_PROFILE_KEY) failed!");
  292.         return (SA_FAIL);
  293.     }
  294.  
  295. #ifdef DEBUG
  296.     (SA_VOID)sa_conn_props(saconn, SA_GET, SA_CONNPROP_HOST, name, 60,
  297.         &namelen);
  298.     name[namelen] = '\0';
  299.     sprintf(buffer, "User '%s' logged in [host %s]", username, name);
  300.     sa_log(sactx, buffer);
  301. #endif    /* DEBUG */
  302.  
  303.     return (SA_SUCCEED);
  304. }
  305.  
  306. /*
  307. **  USER_LOGOUT
  308. **
  309. **    Log out a user.  Free profile resources.
  310. **
  311. **  Parameters:
  312. **    sactx        Sambar Server Application context to release.
  313. **    saconn        Sambar Server User Connection handle.
  314. **
  315. **  Return Values:
  316. **    SA_SUCCESS | SA_FAIL
  317. */
  318. SA_RETCODE SA_PUBLIC
  319. user_logout(sactx, saconn)
  320. SA_CTX        *sactx;
  321. SA_CONN        *saconn;
  322. {
  323.     LOGIN_PROFILE    *profile;
  324. #ifdef DEBUG
  325.     SA_CHAR            buffer[512];
  326. #endif    /* DEBUG */
  327.  
  328.     /* Get the user's pillar handle from the user context                */
  329.     if (sa_conn_key(saconn, SA_GET, LOGIN_PROFILE_KEY, (SA_VOID **)&profile)
  330.         != SA_SUCCEED)
  331.     {
  332.         /* User never completed login                                    */
  333.         return (SA_SUCCEED);
  334.     }
  335.  
  336. #ifdef DEBUG
  337.     sprintf(buffer, "User '%s' logged out.", profile->username);
  338.     sa_log(sactx, buffer);
  339. #endif    /* DEBUG */
  340.  
  341.     (void)free(profile);
  342.  
  343.     return (SA_SUCCEED);
  344. }
  345.  
  346. /*
  347. **  USER_PROFILE
  348. **
  349. **    Respond to a user profile request.
  350. **
  351. **  Parameters:
  352. **    sactx        Sambar Server Application context to release.
  353. **    saconn        Sambar Server User Connection handle.
  354. **    buffer        Profile attribute being queried.
  355. **    buflen        Length of the profile attribute.
  356. **    data        Buffer for the profile result 
  357. **                Note: A maximum of 512 bytes may be written to the data buffer.
  358. **
  359. **  Return Values:
  360. **    SA_SUCCESS | SA_FAIL
  361. */
  362. SA_RETCODE SA_PUBLIC
  363. user_profile(sactx, saconn, buffer, buflen, data)
  364. SA_CTX        *sactx;
  365. SA_CONN        *saconn;
  366. SA_CHAR        *buffer;
  367. SA_INT        buflen;
  368. SA_CHAR        *data;
  369. {
  370.     LOGIN_PROFILE    *profile;
  371.     SA_CHAR            tmp[512];
  372.  
  373.     /* Get the user's profile handle                                     */
  374.     if (sa_conn_key(saconn, SA_GET, LOGIN_PROFILE_KEY, (SA_VOID **)&profile)
  375.         != SA_SUCCEED)
  376.     {
  377.         /* User never completed login                                    */
  378.         return (SA_FAIL);
  379.     }
  380.  
  381.     if (profile == (LOGIN_PROFILE *)NULL)
  382.     {
  383.         sa_log(sactx, "user_profile:  LOGIN_PROFILE_KEY returned NULL!");
  384.         return (SA_FAIL);
  385.     }
  386.  
  387.     /* 
  388.     ** Profile lookup
  389.     */
  390.     if ((buflen == 5) && (strncmp(buffer, "group", 5) == 0))
  391.     {
  392.         strcpy(data, profile->group);
  393.     }
  394.     else if ((buflen == 4) && (strncmp(buffer, "name", 4) == 0))
  395.     {
  396.         strcpy(data, profile->name);
  397.     }
  398.     else
  399.     {
  400.         sprintf(tmp, "Profile attribute '%s' not supported!", buffer);
  401.         sa_log(sactx, tmp);
  402.         return (SA_FAIL);
  403.     }
  404.  
  405.     return (SA_SUCCEED);
  406. }
  407.  
  408. /*
  409. **  USER_ADD
  410. **
  411. **    Add a new user
  412. **
  413. **  Parameters:
  414. **    sactx        Sambar Server context
  415. **    saconn        Sambar Server connection
  416. **    saparams    RPC Parameters
  417. **    infop        Error parameters
  418. **
  419. **  Returns:
  420. **    SA_SUCCEED | SA_FAIL
  421. */
  422. SA_RETCODE SA_PUBLIC
  423. user_add(sactx, saconn, saparams, infop)
  424. SA_CTX        *sactx;
  425. SA_CONN        *saconn;
  426. SA_PARAMS    *saparams;
  427. SA_INT        *infop;
  428. {
  429.     SA_INT        mbox;
  430.     SA_INT        datalen;
  431.     SA_CHAR        *data;
  432.     SA_PASSWD    passwd;
  433.  
  434.     memset(&passwd, 0, sizeof(SA_PASSWD));
  435.     
  436.     mbox = 0;
  437.     if (sa_param(sactx, saparams, "mbox", &data, &datalen) == SA_SUCCEED)
  438.     {
  439.         if ((datalen == 2) && (stricmp(data, "on") == 0))
  440.             mbox = 1;
  441.     }
  442.     
  443.     if (sa_param(sactx, saparams, "password", &data, &datalen) != SA_SUCCEED)
  444.     {
  445.         *infop = SA_E_INVALIDDATA;
  446.         sa_log(sactx, "user_add(): Expected parameter 'password'!");
  447.         return (SA_FAIL);
  448.     }
  449.     
  450.     passwd.passwordlen = MIN(datalen, SA_MAX_NAME);
  451.     if (passwd.passwordlen > 0)
  452.         memcpy(passwd.password, data, passwd.passwordlen);
  453.  
  454.     if (sa_param(sactx, saparams, "group", &data, &datalen) != SA_SUCCEED)
  455.     {
  456.         *infop = SA_E_INVALIDDATA;
  457.         sa_log(sactx, "user_add(): Expected parameter 'group'!");
  458.         return (SA_FAIL);
  459.     }
  460.     
  461.     passwd.grouplen = MIN(datalen, SA_MAX_NAME);
  462.     if (passwd.grouplen > 0)
  463.         memcpy(passwd.group, data, passwd.grouplen);
  464.  
  465.     if (sa_param(sactx, saparams, "name", &data, &datalen) != SA_SUCCEED)
  466.     {
  467.         *infop = SA_E_INVALIDDATA;
  468.         sa_log(sactx, "user_add(): Expected parameter 'name'!");
  469.         return (SA_FAIL);
  470.     }
  471.     
  472.     passwd.namelen = MIN(datalen, SA_MAX_NAME);
  473.     if (passwd.namelen > 0)
  474.         memcpy(passwd.name, data, passwd.namelen);
  475.  
  476.     if (sa_param(sactx, saparams, "dir", &data, &datalen) != SA_SUCCEED)
  477.     {
  478.         *infop = SA_E_INVALIDDATA;
  479.         sa_log(sactx, "user_add(): Expected parameter 'dir'!");
  480.         return (SA_FAIL);
  481.     }
  482.     
  483.     passwd.dirlen = MIN(datalen, SA_MAX_NAME);
  484.     if (passwd.dirlen > 0)
  485.         memcpy(passwd.dir, data, passwd.dirlen);
  486.  
  487.     if (sa_param(sactx, saparams, "ftpprivs", &data, &datalen) != SA_SUCCEED)
  488.     {
  489.         *infop = SA_E_INVALIDDATA;
  490.         sa_log(sactx, "user_add(): Expected parameter 'ftpprivs'!");
  491.         return (SA_FAIL);
  492.     }
  493.  
  494.     passwd.ftpprivs = atol(data);
  495.     
  496.     if (sa_param(sactx, saparams, "ftpmax", &data, &datalen) != SA_SUCCEED)
  497.     {
  498.         *infop = SA_E_INVALIDDATA;
  499.         sa_log(sactx, "user_add(): Expected parameter 'ftpmax'!");
  500.         return (SA_FAIL);
  501.     }
  502.     
  503.     passwd.ftpmax = atol(data);
  504.     if (passwd.ftpmax < 5)
  505.         passwd.ftpmax = 0;
  506.  
  507.     if (sa_param(sactx, saparams, "username", &data, &datalen) != SA_SUCCEED)
  508.     {
  509.         *infop = SA_E_INVALIDDATA;
  510.         sa_log(sactx, "user_add(): Expected parameter 'username'!");
  511.         return (SA_FAIL);
  512.     }
  513.  
  514.     if ((datalen == 0) || (datalen > SA_MAX_NAME))
  515.     {
  516.         *infop = SA_E_INVALIDDATA;
  517.         sa_log(sactx, "user_add(): 'username' field left NULL!");
  518.         return (SA_FAIL);
  519.     }
  520.  
  521.     /* Create the user account.                                            */
  522.     if (sa_passwd_add(sactx, data, datalen, &passwd) != SA_SUCCEED)
  523.     {
  524.         *infop = SA_E_ALREADYDEFINED;
  525.         sa_log(sactx, "user_add(): sa_passwd_add() failed!");
  526.         return (SA_FAIL);
  527.     }
  528.  
  529.     /* Create the user mailbox.                                            */
  530.     if (mbox)
  531.     {
  532.         if (sa_mbox_create(sactx, data) != SA_SUCCEED)
  533.         {
  534.             *infop = SA_E_ALREADYDEFINED;
  535.             sa_log(sactx, "user_add(): sa_mbox_create() failed!");
  536.             return (SA_FAIL);
  537.         }
  538.     }
  539.  
  540.     return (SA_SUCCEED);
  541. }
  542.  
  543. /*
  544. **  USER_UPDATE
  545. **
  546. **    Update an existing user
  547. **
  548. **  Parameters:
  549. **    sactx        Sambar Server context
  550. **    saconn        Sambar Server connection
  551. **    saparams    RPC Parameters
  552. **    infop        Error parameters
  553. **
  554. **  Returns:
  555. **    SA_SUCCEED | SA_FAIL
  556. */
  557. SA_RETCODE SA_PUBLIC
  558. user_update(sactx, saconn, saparams, infop)
  559. SA_CTX        *sactx;
  560. SA_CONN        *saconn;
  561. SA_PARAMS    *saparams;
  562. SA_INT        *infop;
  563. {
  564.     SA_INT        mbox;
  565.     SA_INT        datalen;
  566.     SA_CHAR        *data;
  567.     SA_PASSWD    passwd;
  568.  
  569.     memset(&passwd, 0, sizeof(SA_PASSWD));
  570.  
  571.     mbox = 0;
  572.     if (sa_param(sactx, saparams, "mbox", &data, &datalen) == SA_SUCCEED)
  573.     {
  574.         if ((datalen == 2) && (stricmp(data, "on") == 0))
  575.             mbox = 1;
  576.     }
  577.     
  578.     if (sa_param(sactx, saparams, "password", &data, &datalen) != SA_SUCCEED)
  579.     {
  580.         *infop = SA_E_INVALIDDATA;
  581.         sa_log(sactx, "user_update(): Expected parameter 'password'!");
  582.         return (SA_FAIL);
  583.     }
  584.     
  585.     passwd.passwordlen = MIN(datalen, SA_MAX_NAME);
  586.     if (passwd.passwordlen > 0)
  587.         memcpy(passwd.password, data, passwd.passwordlen);
  588.  
  589.     if (sa_param(sactx, saparams, "group", &data, &datalen) != SA_SUCCEED)
  590.     {
  591.         *infop = SA_E_INVALIDDATA;
  592.         sa_log(sactx, "user_update(): Expected parameter 'group'!");
  593.         return (SA_FAIL);
  594.     }
  595.     
  596.     passwd.grouplen = MIN(datalen, SA_MAX_NAME);
  597.     if (passwd.grouplen > 0)
  598.         memcpy(passwd.group, data, passwd.grouplen);
  599.  
  600.     if (sa_param(sactx, saparams, "name", &data, &datalen) != SA_SUCCEED)
  601.     {
  602.         *infop = SA_E_INVALIDDATA;
  603.         sa_log(sactx, "user_update(): Expected parameter 'name'!");
  604.         return (SA_FAIL);
  605.     }
  606.     
  607.     passwd.namelen = MIN(datalen, SA_MAX_NAME);
  608.     if (passwd.namelen > 0)
  609.         memcpy(passwd.name, data, passwd.namelen);
  610.  
  611.     if (sa_param(sactx, saparams, "dir", &data, &datalen) != SA_SUCCEED)
  612.     {
  613.         *infop = SA_E_INVALIDDATA;
  614.         sa_log(sactx, "user_update(): Expected parameter 'dir'!");
  615.         return (SA_FAIL);
  616.     }
  617.     
  618.     passwd.dirlen = MIN(datalen, SA_MAX_NAME);
  619.     if (passwd.dirlen > 0)
  620.         memcpy(passwd.dir, data, passwd.dirlen);
  621.  
  622.     if (sa_param(sactx, saparams, "ftpprivs", &data, &datalen) != SA_SUCCEED)
  623.     {
  624.         *infop = SA_E_INVALIDDATA;
  625.         sa_log(sactx, "user_update(): Expected parameter 'ftpprivs'!");
  626.         return (SA_FAIL);
  627.     }
  628.     
  629.     passwd.ftpprivs = atol(data);
  630.  
  631.     if (sa_param(sactx, saparams, "ftpmax", &data, &datalen) != SA_SUCCEED)
  632.     {
  633.         *infop = SA_E_INVALIDDATA;
  634.         sa_log(sactx, "user_update(): Expected parameter 'ftpmax'!");
  635.         return (SA_FAIL);
  636.     }
  637.     
  638.     passwd.ftpmax = atol(data);
  639.     if (passwd.ftpmax < 5)
  640.         passwd.ftpmax = 0;
  641.  
  642.     if (sa_param(sactx, saparams, "username", &data, &datalen) != SA_SUCCEED)
  643.     {
  644.         *infop = SA_E_INVALIDDATA;
  645.         sa_log(sactx, "user_update(): Expected parameter 'username'!");
  646.         return (SA_FAIL);
  647.     }
  648.  
  649.     if ((datalen == 0) || (datalen > SA_MAX_NAME))
  650.     {
  651.         *infop = SA_E_INVALIDDATA;
  652.         sa_log(sactx, "user_update(): 'username' field left NULL!");
  653.         return (SA_FAIL);
  654.     }
  655.  
  656.     if (sa_passwd_update(sactx, data, datalen, &passwd) != SA_SUCCEED)
  657.     {
  658.         *infop = SA_E_ALREADYDEFINED;
  659.         sa_log(sactx, "user_update(): sa_passwd_update() failed!");
  660.         return (SA_FAIL);
  661.     }
  662.  
  663.     /* Create the user mailbox.                                            */
  664.     if (mbox)
  665.     {
  666.         if (sa_mbox_create(sactx, data) != SA_SUCCEED)
  667.         {
  668.             *infop = SA_E_ALREADYDEFINED;
  669.             sa_log(sactx, "user_update(): sa_mbox_create() failed!");
  670.             return (SA_FAIL);
  671.         }
  672.     }
  673.  
  674.     return (SA_SUCCEED);
  675. }
  676.  
  677. /*
  678. **  USER_DELETE
  679. **
  680. **    Delete an existing user
  681. **
  682. **  Parameters:
  683. **    sactx        Sambar Server context
  684. **    saconn        Sambar Server connection
  685. **    saparams    RPC Parameters
  686. **    infop        Error parameters
  687. **
  688. **  Returns:
  689. **    SA_SUCCEED | SA_FAIL
  690. */
  691. SA_RETCODE SA_PUBLIC
  692. user_delete(sactx, saconn, saparams, infop)
  693. SA_CTX        *sactx;
  694. SA_CONN        *saconn;
  695. SA_PARAMS    *saparams;
  696. SA_INT        *infop;
  697. {
  698.     SA_INT        datalen;
  699.     SA_INT        sysadminlen;
  700.     SA_CHAR        *data;
  701.     SA_CHAR        sysadmin[SA_MAX_NAME + 1];
  702.  
  703.     /* Get the sysadmin user (disallow deletes)                            */
  704.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_SYSADMIN, (SA_BYTE *)sysadmin,
  705.         SA_MAX_NAME, &sysadminlen) != SA_SUCCEED)
  706.     {
  707.         sa_log(sactx, "user_delete(): failure retrieving system admin user!");
  708.         return (SA_FAIL);
  709.     }
  710.  
  711.     if (sa_param(sactx, saparams, "username", &data, &datalen) != SA_SUCCEED)
  712.     {
  713.         *infop = SA_E_INVALIDDATA;
  714.         sa_log(sactx, "user_delete(): Expected parameter 'username'!");
  715.         return (SA_FAIL);
  716.     }
  717.  
  718.     if ((datalen == 0) || (datalen > SA_MAX_NAME))
  719.     {
  720.         *infop = SA_E_INVALIDDATA;
  721.         sa_log(sactx, "user_delete(): 'username' field left NULL!");
  722.         return (SA_FAIL);
  723.     }
  724.  
  725.     /* Don't allow the deletion of the system administrator                */
  726.     if ((datalen != sysadminlen) || (memcmp(sysadmin, data, sysadminlen) != 0))
  727.     {
  728.         (SA_VOID)sa_passwd_delete(sactx, data, datalen);
  729.         (SA_VOID)sa_mbox_delete(sactx, data);
  730.     }
  731.  
  732.     return (SA_SUCCEED);
  733. }
  734.  
  735. /*
  736. **  USER_SELECT
  737. **
  738. **    List all users for selection.
  739. **
  740. **  Parameters:
  741. **    sactx        Sambar Server context
  742. **    saconn        Sambar Server connection
  743. **    saparams    RPC Parameters
  744. **    infop        Error parameters
  745. **
  746. **  Returns:
  747. **    SA_SUCCEED | SA_FAIL
  748. **
  749. **  Notes:
  750. **    This list is truncated at 500 names.
  751. */
  752. SA_RETCODE SA_PUBLIC
  753. user_select(sactx, saconn, saparams, infop)
  754. SA_CTX        *sactx;
  755. SA_CONN        *saconn;
  756. SA_PARAMS    *saparams;
  757. SA_INT        *infop;
  758. {
  759.     SA_INT            i;
  760.     SA_BOOL            selected;
  761.     SA_INT            usernamelen;
  762.     SA_INT            numusers;
  763.     SA_CHAR            *username;
  764.     SA_USER            users[500];
  765.     SA_CHAR            buffer[512];
  766.  
  767.     /* If a username is provided make it SELECTED in the OPTION list    */
  768.     (SA_VOID)sa_param(sactx, saparams, "username", &username, &usernamelen);
  769.  
  770.     if (sa_passwd_list(sactx, users, 500, &numusers) != SA_SUCCEED)
  771.     {
  772.         sa_log(sactx, "user_select(): failure retrieving names list!");
  773.         return (SA_FAIL);
  774.     }
  775.  
  776.     /* We could sort the names alphabetically at this point...            */
  777.  
  778.     /* Display the list of users.                                        */
  779.     for (i = 0; i < numusers; i++)
  780.     {
  781.         selected = 0;
  782.         if ((users[i].usernamelen == usernamelen) &&
  783.             (memcmp(username, users[i].username, usernamelen) == 0))
  784.         {
  785.             selected = 1;
  786.         }
  787.  
  788.         sprintf(buffer, "<OPTION %s>%s\n", (selected ? "SELECTED" : ""),
  789.                 users[i].username);
  790.  
  791.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  792.             return (SA_FAIL);
  793.     }
  794.  
  795.     return (SA_SUCCEED);
  796. }
  797.  
  798. /*
  799. **  USER_LIST
  800. **
  801. **    List all users for delete or update.
  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. **  Notes:
  813. **    This list is truncated at 500 names.
  814. **    List users by group...
  815. */
  816. SA_RETCODE SA_PUBLIC
  817. user_list(sactx, saconn, saparams, infop)
  818. SA_CTX        *sactx;
  819. SA_CONN        *saconn;
  820. SA_PARAMS    *saparams;
  821. SA_INT        *infop;
  822. {
  823.     SA_INT            i;
  824.     SA_INT            j;
  825.     SA_INT            sysadminlen;
  826.     SA_INT            numusers;
  827.     SA_INT            numgroups;
  828.     SA_GROUP        groups[100];
  829.     SA_USER            users[500];
  830.     SA_CHAR            sysadmin[SA_MAX_NAME + 1];
  831.     SA_CHAR            buffer[512];
  832.  
  833.     /* Get the sysadmin user (disallow deletes)                            */
  834.     if (sa_ctx_props(sactx, SA_GET, SA_CTXPROP_SYSADMIN, (SA_BYTE *)sysadmin,
  835.         SA_MAX_NAME, &sysadminlen) != SA_SUCCEED)
  836.     {
  837.         sa_log(sactx, "user_list(): failure retrieving system admin user!");
  838.         return (SA_FAIL);
  839.     }
  840.  
  841.     if (sa_passwd_list(sactx, users, 500, &numusers) != SA_SUCCEED)
  842.     {
  843.         sa_log(sactx, "user_list(): failure retrieving names list!");
  844.         return (SA_FAIL);
  845.     }
  846.  
  847.     if (sa_group_list(sactx, groups, 100, &numgroups) != SA_SUCCEED)
  848.     {
  849.         sa_log(sactx, "user_list(): failure retrieving groups list!");
  850.         return (SA_FAIL);
  851.     }
  852.  
  853.     /* We could sort the list alphabetically at this point.                */
  854.  
  855.     /*
  856.     ** Display the users by "group".
  857.     ** Zero the usernamelen after displaying so we can put the rest in
  858.     ** the "other" list.
  859.     */
  860.     for (j = 0; j < numgroups; j++)
  861.     {
  862.         sprintf(buffer, "<FONT SIZE=+1 COLOR=#990033>%s</FONT><BLOCKQUOTE>\n",
  863.             groups[j].name);
  864.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  865.             return (SA_FAIL);
  866.         
  867.         /* Display the users in that group.                                */
  868.         for (i = 0; i < numusers; i++)
  869.         {
  870.             if ((users[i].usernamelen > 0) && 
  871.                 (users[i].grouplen == groups[j].namelen) &&
  872.                 (memcmp(users[i].group, groups[j].name, users[i].grouplen)==0))
  873.             {
  874.                 /* Make sure we don't display the user twice.            */
  875.                 users[i].usernamelen = 0;
  876.  
  877.                 if ((users[i].usernamelen != sysadminlen) ||
  878.                     (strncmp(sysadmin, users[i].username, sysadminlen) != 0))
  879.                 {
  880.                     sprintf(buffer, 
  881.                         "<A HREF=\"/session/deluser?username=%s&RCpage=/sysadmin/usermgmt/userlist.stm\" onClick=\"return confirmDelete()\"><IMG border=0 HEIGHT=20 WIDTH=20 SRC=\"/sysimage/system/trash.gif\"></A>\n",
  882.                         users[i].username);
  883.  
  884.                     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  885.                         return (SA_FAIL);
  886.                 }
  887.  
  888.                 sprintf(buffer, 
  889.                     "<A HREF=\"/sysadmin/usermgmt/upduser.stm?RCSusername=%s\" TARGET=body><IMG border=0 HEIGHT=20 WIDTH=20 SRC=\"/sysimage/system/info.gif\"> %s</A><BR>\n",
  890.                     users[i].username, users[i].username);
  891.  
  892.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  893.                     return (SA_FAIL);
  894.             }
  895.         }
  896.  
  897.         if (sa_conn_send(saconn, "</BLOCKQUOTE>", SA_NULLTERM) != SA_SUCCEED)
  898.             return (SA_FAIL);
  899.     }
  900.  
  901.     /* Display the "other" group                                        */
  902.     sprintf(buffer, "<FONT SIZE=+1 COLOR=#990066>%s</FONT><BLOCKQUOTE>\n", 
  903.         SA_DEFAULT_GROUP);
  904.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  905.         return (SA_FAIL);
  906.         
  907.     /* Display the users in that group.                                    */
  908.     for (i = 0; i < numusers; i++)
  909.     {
  910.         /* Display all users not in any other group.                    */
  911.         if (users[i].usernamelen > 0)
  912.         {
  913.             if ((users[i].usernamelen != sysadminlen) ||
  914.                 (strncmp(sysadmin, users[i].username, sysadminlen) != 0))
  915.             {
  916.                 sprintf(buffer, 
  917.                     "<A HREF=\"/session/deluser?username=%s&RCpage=/sysadmin/usermgmt/userlist.stm\" onClick=\"return confirmDelete()\"><IMG border=0 HEIGHT=15 WIDTH=15 SRC=\"/sysimage/system/trash.gif\"></A>\n",
  918.                     users[i].username);
  919.  
  920.                 if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  921.                     return (SA_FAIL);
  922.             }
  923.  
  924.             sprintf(buffer, 
  925.                 "<A HREF=\"/sysadmin/usermgmt/upduser.stm?RCSusername=%s\" TARGET=body><IMG border=0 HEIGHT=15 WIDTH=15 SRC=\"/sysimage/system/info.gif\"> %s</A><BR>\n",
  926.                 users[i].username, users[i].username);
  927.  
  928.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  929.                 return (SA_FAIL);
  930.         }
  931.  
  932.     }
  933.  
  934.     if (sa_conn_send(saconn, "</BLOCKQUOTE>\n", SA_NULLTERM) != SA_SUCCEED)
  935.         return (SA_FAIL);
  936.  
  937.     return (SA_SUCCEED);
  938. }
  939.  
  940. /*
  941. **  USER_PASSWD
  942. **
  943. **    Update a user' password.
  944. **
  945. **  Parameters:
  946. **    sactx        Sambar Server context
  947. **    saconn        Sambar Server connection
  948. **    saparams    RPC Parameters
  949. **    infop        Error parameters
  950. **
  951. **  Returns:
  952. **    SA_SUCCEED | SA_FAIL
  953. */
  954. SA_RETCODE SA_PUBLIC
  955. user_passwd(sactx, saconn, saparams, infop)
  956. SA_CTX        *sactx;
  957. SA_CONN        *saconn;
  958. SA_PARAMS    *saparams;
  959. SA_INT        *infop;
  960. {
  961.     SA_INT        datalen;
  962.     SA_INT        passwordlen;
  963.     SA_INT        usernamelen;
  964.     SA_CHAR        *data;
  965.     SA_CHAR        *password;
  966.     SA_CHAR        *username;
  967.     SA_PASSWD    passwd;
  968.  
  969.     /* What username is being updated?                                    */
  970.     if (sa_param(sactx, saparams, "username", &username, &usernamelen) 
  971.         != SA_SUCCEED)
  972.     {
  973.         *infop = SA_E_INVALIDDATA;
  974.         sa_log(sactx, "user_passwd(): Expected parameter 'username'!");
  975.         return (SA_FAIL);
  976.     }
  977.  
  978.     if ((usernamelen == 0) || (usernamelen > SA_MAX_NAME))
  979.     {
  980.         *infop = SA_E_INVALIDDATA;
  981.         sa_log(sactx, "user_update(): 'username' field left NULL!");
  982.         return (SA_FAIL);
  983.     }
  984.  
  985.     /* Lookup the username provided for update.                            */
  986.     if (sa_passwd_lookup(sactx, username, usernamelen, &passwd) != SA_SUCCEED)
  987.     {
  988.         *infop = SA_E_INVALIDDATA;
  989.         sa_log(sactx, "user_passwd(): sa_passwd_lookup() failed!");
  990.         return (SA_FAIL);
  991.     }
  992.  
  993.     /* Make sure that the password is valid.                        */
  994.     if (sa_param(sactx, saparams, "password", &data, &datalen) != SA_SUCCEED)
  995.     {
  996.         *infop = SA_E_INVALIDDATA;
  997.         sa_log(sactx, "user_passwd(): Expected parameter 'password'!");
  998.         return (SA_FAIL);
  999.     }
  1000.     
  1001.     /* Compare with the existing password.                            */
  1002.     if (datalen != passwd.passwordlen)
  1003.     {    
  1004.         *infop = SA_E_INVALIDDATA;
  1005.         sa_log(sactx, "user_passwd(): Invalid password provided.");
  1006.         return (SA_FAIL);
  1007.     }
  1008.     
  1009.     if (datalen > 0)
  1010.     {
  1011.         if (memcmp(passwd.password, data, datalen) != 0)
  1012.         {
  1013.             *infop = SA_E_INVALIDDATA;
  1014.             sa_log(sactx, "user_passwd(): Invalid password provided.");
  1015.             return (SA_FAIL);
  1016.         }
  1017.     }
  1018.  
  1019.     /* Get the new password.                                            */
  1020.     if (sa_param(sactx, saparams, "newpasswd", &password, &passwordlen) 
  1021.         != SA_SUCCEED)
  1022.     {
  1023.         *infop = SA_E_INVALIDDATA;
  1024.         sa_log(sactx, "user_passwd(): Expected parameter 'newpasswd'!");
  1025.         return (SA_FAIL);
  1026.     }
  1027.     
  1028.     /* Confirm the new password.                                        */
  1029.     if (sa_param(sactx, saparams, "confpasswd", &data, &datalen) 
  1030.         != SA_SUCCEED)
  1031.     {
  1032.         *infop = SA_E_INVALIDDATA;
  1033.         sa_log(sactx, "user_passwd(): Expected parameter 'confpasswd'!");
  1034.         return (SA_FAIL);
  1035.     }
  1036.  
  1037.     /* Does the new password and confirm password match?                */
  1038.     if ((passwordlen > 0) && (datalen > 0))
  1039.     {
  1040.         if ((passwordlen != datalen) ||
  1041.             (memcmp(password, data, datalen) != 0))
  1042.         {
  1043.             *infop = SA_E_INVALIDDATA;
  1044.             sa_log(sactx, 
  1045.                 "user_passwd(): New & confirmation password do not match!");
  1046.             return (SA_FAIL);
  1047.         }
  1048.     }
  1049.     
  1050.     passwd.passwordlen = MIN(datalen, SA_MAX_NAME);
  1051.     if (passwd.passwordlen > 0)
  1052.         memcpy(passwd.password, data, passwd.passwordlen);
  1053.  
  1054.     if (sa_passwd_update(sactx, username, usernamelen, &passwd) != SA_SUCCEED)
  1055.     {
  1056.         sa_log(sactx, "user_passwd(): sa_passwd_update() failed!");
  1057.         return (SA_FAIL);
  1058.     }
  1059.  
  1060.     return (SA_SUCCEED);
  1061. }
  1062.  
  1063. /*
  1064. **  USER_PROP
  1065. **
  1066. **    Lookup and return a single user property.
  1067. **
  1068. **  Parameters:
  1069. **    sactx        Sambar Server context
  1070. **    saconn        Sambar Server connection
  1071. **    saparams    RPC Parameters
  1072. **    infop        Error parameters
  1073. **
  1074. **  Return Values:
  1075. **    SA_SUCCESS | SA_FAIL
  1076. */
  1077. SA_RETCODE SA_PUBLIC
  1078. user_prop(sactx, saconn, saparams, infop)
  1079. SA_CTX        *sactx;
  1080. SA_CONN        *saconn;
  1081. SA_PARAMS    *saparams;
  1082. SA_INT        *infop;
  1083. {
  1084.     SA_PASSWD            passwd;
  1085.     SA_INT                userlen;
  1086.     SA_CHAR                *user;
  1087.     SA_INT                proplen;
  1088.     SA_CHAR                *prop;
  1089.     SA_CHAR                buffer[512];
  1090.  
  1091.     /* Get the page to direct to for user update                        */
  1092.     if (sa_param(sactx, saparams, "username", &user, &userlen) != SA_SUCCEED)
  1093.     {
  1094.         *infop = SA_E_INVALIDDATA;
  1095.         sa_log(sactx, "user_prop(): Expected parameter 'username'!");
  1096.         return (SA_FAIL);
  1097.     }
  1098.  
  1099.     if ((userlen == 0) || (userlen > SA_MAX_NAME))
  1100.     {
  1101.         *infop = SA_E_INVALIDDATA;
  1102.         sa_log(sactx, "user_prop(): 'username' field left NULL!");
  1103.         return (SA_FAIL);
  1104.     }
  1105.  
  1106.     /* Get the property being looked up.                                */
  1107.     if (sa_param(sactx, saparams, "prop", &prop, &proplen) != SA_SUCCEED)
  1108.     {
  1109.         *infop = SA_E_INVALIDDATA;
  1110.         sa_log(sactx, "user_prop(): Expected parameter 'prop'!");
  1111.         return (SA_FAIL);
  1112.     }
  1113.  
  1114.     if ((proplen == 0) || (proplen > SA_MAX_NAME))
  1115.     {
  1116.         *infop = SA_E_INVALIDDATA;
  1117.         sa_log(sactx, "user_prop(): 'prop' field left NULL!");
  1118.         return (SA_FAIL);
  1119.     }
  1120.  
  1121.     if (sa_passwd_lookup(sactx, user, userlen, &passwd) != SA_SUCCEED)
  1122.     {
  1123.         sprintf(buffer, "User lookup for '%s' failed.", user);
  1124.         sa_log(sactx, buffer);
  1125.         *infop = SA_E_INVALIDDATA;
  1126.         return (SA_FAIL);
  1127.     }
  1128.  
  1129.     /* Lookup and return the appropriate property                        */
  1130.     if (strcmp(prop, "group") == 0)
  1131.     {
  1132.         if (sa_conn_send(saconn, passwd.group, passwd.grouplen) != SA_SUCCEED)
  1133.             return (SA_FAIL);
  1134.     }
  1135.     else if (strcmp(prop, "password") == 0)
  1136.     {
  1137.         if (sa_conn_send(saconn, passwd.password, passwd.passwordlen) 
  1138.             != SA_SUCCEED)
  1139.         {
  1140.             return (SA_FAIL);
  1141.         }
  1142.     }
  1143.     else if (strcmp(prop, "name") == 0)
  1144.     {
  1145.         if (sa_conn_send(saconn, passwd.name, passwd.namelen) != SA_SUCCEED)
  1146.             return (SA_FAIL);
  1147.     }
  1148.     else if (strcmp(prop, "dir") == 0)
  1149.     {
  1150.         if (sa_conn_send(saconn, passwd.dir, passwd.dirlen) != SA_SUCCEED)
  1151.             return (SA_FAIL);
  1152.     }
  1153.     else if (strcmp(prop, "ftpprivs") == 0)
  1154.     {
  1155.         if (sa_param(sactx, saparams, "checked", &prop, &proplen) == SA_SUCCEED)
  1156.         {
  1157.             int        tmp;
  1158.  
  1159.             tmp = 0;
  1160.             if (proplen > 0)
  1161.                 tmp = atoi(prop);
  1162.         
  1163.             if (tmp == passwd.ftpprivs)
  1164.             {
  1165.                 if (sa_conn_send(saconn, "CHECKED", SA_NULLTERM) != SA_SUCCEED)
  1166.                     return (SA_FAIL);
  1167.             }
  1168.         }
  1169.         else
  1170.         {
  1171.             sprintf(buffer, "%ld", passwd.ftpprivs);
  1172.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1173.                 return (SA_FAIL);
  1174.         }
  1175.     }
  1176.     else if (strcmp(prop, "ftpmax") == 0)
  1177.     {
  1178.         if (passwd.ftpmax < 5)
  1179.             passwd.ftpmax = 0;
  1180.         sprintf(buffer, "%ld", passwd.ftpmax);
  1181.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1182.             return (SA_FAIL);
  1183.     }
  1184.     else if (strcmp(prop, "mbox") == 0)
  1185.     {
  1186.         if (sa_mbox_exists(sactx, user))
  1187.             strcpy(buffer, "CHECKED");
  1188.         else
  1189.             strcpy(buffer, "");
  1190.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1191.             return (SA_FAIL);
  1192.     }
  1193.     else 
  1194.     {
  1195.         sprintf(buffer, "User lookup for property '%s' failed.", prop);
  1196.         sa_log(sactx, buffer);
  1197.         *infop = SA_E_INVALIDDATA;
  1198.         return (SA_FAIL);
  1199.     }
  1200.  
  1201.     return (SA_SUCCEED);
  1202. }
  1203.  
  1204. /*
  1205. **  USER_MAILLIST
  1206. **
  1207. **    List all mail users for delete or update.
  1208. **
  1209. **  Parameters:
  1210. **    sactx        Sambar Server context
  1211. **    saconn        Sambar Server connection
  1212. **    saparams    RPC Parameters
  1213. **    infop        Error parameters
  1214. **
  1215. **  Returns:
  1216. **    SA_SUCCEED | SA_FAIL
  1217. **
  1218. **  Notes:
  1219. **    This list is truncated at 500 names.
  1220. */
  1221. SA_RETCODE SA_PUBLIC
  1222. user_maillist(sactx, saconn, saparams, infop)
  1223. SA_CTX        *sactx;
  1224. SA_CONN        *saconn;
  1225. SA_PARAMS    *saparams;
  1226. SA_INT        *infop;
  1227. {
  1228.     SA_INT            i;
  1229.     SA_INT            numusers;
  1230.     SA_USER            users[500];
  1231.     SA_CHAR            buffer[512];
  1232.  
  1233.     if (sa_passwd_list(sactx, users, 500, &numusers) != SA_SUCCEED)
  1234.     {
  1235.         sa_log(sactx, "user_list(): failure retrieving names list!");
  1236.         return (SA_FAIL);
  1237.     }
  1238.  
  1239.     /* Sort the mail user list alphabetically at this point.            */
  1240.  
  1241.     if (sa_conn_send(saconn, "<TABLE BORDER=0 CELLPADDING=2>\n", SA_NULLTERM) 
  1242.         != SA_SUCCEED)
  1243.     {
  1244.         return (SA_FAIL);
  1245.     }
  1246.  
  1247.     if (sa_conn_send(saconn, 
  1248.         "<TR><TH>User</TH><TH align=center>Mailbox</TH></TR>\n",
  1249.         SA_NULLTERM) != SA_SUCCEED)
  1250.     {
  1251.         return (SA_FAIL);
  1252.     }
  1253.  
  1254.     /*
  1255.     ** Display the mail users
  1256.     */
  1257.     for (i = 0; i < numusers; i++)
  1258.     {
  1259.         sprintf(buffer, "<TR><TD><b>%s</b> </TD><TD>", users[i].username);
  1260.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1261.             return (SA_FAIL);
  1262.  
  1263.         if (sa_mbox_exists(sactx, users[i].username))
  1264.         {
  1265.             sprintf(buffer, 
  1266.                 "<A HREF=\"/session/usermbox?action=delete&username=%s&RCpage=/sysadmin/mail/users.stm\"><font color=#990000>Delete</font></A>",
  1267.                 users[i].username);
  1268.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1269.                 return (SA_FAIL);
  1270.         }
  1271.         else
  1272.         {
  1273.             sprintf(buffer, 
  1274.                 "<A HREF=\"/session/usermbox?action=create&username=%s&RCpage=/sysadmin/mail/users.stm\"><font color=#009900>Create</font></A>", 
  1275.                 users[i].username);
  1276.             if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1277.                 return (SA_FAIL);
  1278.         }
  1279.  
  1280.         if (sa_conn_send(saconn, "</TD></TR>\n", SA_NULLTERM) != SA_SUCCEED)
  1281.             return (SA_FAIL);
  1282.     }
  1283.  
  1284.     if (sa_conn_send(saconn, "</TABLE>\n", SA_NULLTERM) != SA_SUCCEED)
  1285.         return (SA_FAIL);
  1286.  
  1287.     return (SA_SUCCEED);
  1288. }
  1289.  
  1290. /*
  1291. **  USER_MBOX
  1292. **
  1293. **    Update an user mailbox
  1294. **
  1295. **  Parameters:
  1296. **    sactx        Sambar Server context
  1297. **    saconn        Sambar Server connection
  1298. **    saparams    RPC Parameters
  1299. **    infop        Error parameters
  1300. **
  1301. **  Returns:
  1302. **    SA_SUCCEED | SA_FAIL
  1303. */
  1304. SA_RETCODE SA_PUBLIC
  1305. user_mailbox(sactx, saconn, saparams, infop)
  1306. SA_CTX        *sactx;
  1307. SA_CONN        *saconn;
  1308. SA_PARAMS    *saparams;
  1309. SA_INT        *infop;
  1310. {
  1311.     SA_BOOL        create;
  1312.     SA_INT        datalen;
  1313.     SA_CHAR        *data;
  1314.     SA_PASSWD    passwd;
  1315.  
  1316.     if (sa_param(sactx, saparams, "action", &data, &datalen) != SA_SUCCEED)
  1317.     {
  1318.         *infop = SA_E_INVALIDDATA;
  1319.         sa_log(sactx, "user_mailbox(): Expected parameter 'action'!");
  1320.         return (SA_FAIL);
  1321.     }
  1322.  
  1323.     if (stricmp(data, "create") == 0)
  1324.     {
  1325.         create = 1;
  1326.     }
  1327.     else if (stricmp(data, "delete") == 0)
  1328.     {
  1329.         create = 0;
  1330.     }
  1331.     else
  1332.     {
  1333.         *infop = SA_E_INVALIDDATA;
  1334.         sa_log(sactx, "user_mailbox(): Parameter 'action' not create/delete!");
  1335.         return (SA_FAIL);
  1336.     }
  1337.     
  1338.     if (sa_param(sactx, saparams, "username", &data, &datalen) != SA_SUCCEED)
  1339.     {
  1340.         *infop = SA_E_INVALIDDATA;
  1341.         sa_log(sactx, "user_mailbox(): Expected parameter 'username'!");
  1342.         return (SA_FAIL);
  1343.     }
  1344.  
  1345.     /* Verify the user account exists.                                    */
  1346.     if (sa_passwd_lookup(sactx, data, datalen, &passwd) == SA_SUCCEED)
  1347.     {
  1348.         /* Create the user mailbox.                                        */
  1349.         if (create)
  1350.         {
  1351.             if (sa_mbox_create(sactx, data) != SA_SUCCEED)
  1352.                 sa_log(sactx, "user_mailbox(): sa_mbox_create() failed!");
  1353.         }
  1354.         else
  1355.         {
  1356.             if (sa_mbox_delete(sactx, data) != SA_SUCCEED)
  1357.                 sa_log(sactx, "user_mailbox(): sa_mbox_delete() failed!");
  1358.         }
  1359.     }
  1360.  
  1361.     return (SA_SUCCEED);
  1362. }
  1363.  
  1364.  
  1365. /*
  1366. **  FTP_CONNECT
  1367. **
  1368. **    Process an FTP Connect request. Verify the username/password against 
  1369. **    the Sambar Server password interfaces and return the root directory
  1370. **    and priviledges.
  1371. **
  1372. **  Parameters:
  1373. **    sactx            Sambar Server Application context to release.
  1374. **    saconn            Sambar Server User Connection handle.
  1375. **    username        Name of the user logging in.
  1376. **    usernamelen        Length of the user name
  1377. **    password        Password of the user logging in.
  1378. **    passwordlen        Length of the password.
  1379. **    ftpresp            FTP response structure.
  1380. **
  1381. **  Return Values:
  1382. **    SA_SUCCESS         Login Accepted.
  1383. **    SA_FAIL            Login Denied.
  1384. */
  1385. SA_RETCODE SA_PUBLIC
  1386. ftp_connect(sactx, name, namelen, password, passwordlen, ftpresp)
  1387. SA_CTX        *sactx;
  1388. SA_CHAR        *name;
  1389. SA_INT        namelen;
  1390. SA_CHAR        *password;
  1391. SA_INT        passwordlen;
  1392. SA_FTP        *ftpresp;
  1393. {
  1394.     SA_PASSWD            passwd;
  1395.     SA_CHAR                buffer[512];
  1396.  
  1397.     if (sa_passwd_lookup(sactx, name, namelen, &passwd) != SA_SUCCEED)
  1398.     {
  1399.         sprintf(buffer, "FTP login for user '%s' failed.", name);
  1400.         sa_log(sactx, buffer);
  1401.         return (SA_FAIL);
  1402.     }
  1403.  
  1404.     /* Verify the passwords are the same                                */
  1405.     if ((passwd.passwordlen != passwordlen) ||
  1406.         (strncmp(passwd.password, password, passwordlen) != 0))
  1407.     {
  1408.         /* Special case for anonymous user - NULL password match OK        */
  1409.         if ((namelen != 9) || (strncmp(name, "anonymous", 9) != 0))
  1410.         {
  1411.             sprintf(buffer, 
  1412.                 "FTP login for user '%s' failed - bad password (%s)", 
  1413.                 name, password);
  1414.             sa_log(sactx, buffer);
  1415.             return (SA_FAIL);
  1416.         }
  1417.     }
  1418.  
  1419.     /* Return the directory and access priviledges                    */
  1420.     ftpresp->privs = passwd.ftpprivs;
  1421.     ftpresp->ftpmax = passwd.ftpmax;
  1422.     ftpresp->dirlen = passwd.dirlen;
  1423.     if (ftpresp->dirlen > 0)
  1424.         strncpy(ftpresp->dir, passwd.dir, ftpresp->dirlen);
  1425.  
  1426.     ftpresp->dir[ftpresp->dirlen] = '\0';
  1427.  
  1428. #ifdef DEBUG
  1429.     sprintf(buffer, "FTP User '%s' logged in.", name);
  1430.     sa_log(sactx, buffer);
  1431. #endif    /* DEBUG */
  1432.  
  1433.     return (SA_SUCCEED);
  1434. }
  1435.  
  1436. /*
  1437. **  MAIL_CONNECT
  1438. **
  1439. **    Process an MAIL Connect request. Verify the username/password against 
  1440. **    the Sambar Server password interfaces.
  1441. **
  1442. **  Parameters:
  1443. **    sactx            Sambar Server Application context to release.
  1444. **    saconn            Sambar Server User Connection handle.
  1445. **    username        Name of the user logging in.
  1446. **    usernamelen        Length of the user name
  1447. **    password        Password of the user logging in.
  1448. **    passwordlen        Length of the password.
  1449. **
  1450. **  Return Values:
  1451. **    SA_SUCCESS         Login Accepted.
  1452. **    SA_FAIL            Login Denied.
  1453. */
  1454. SA_RETCODE SA_PUBLIC
  1455. mail_connect(sactx, name, namelen, password, passwordlen)
  1456. SA_CTX        *sactx;
  1457. SA_CHAR        *name;
  1458. SA_INT        namelen;
  1459. SA_CHAR        *password;
  1460. SA_INT        passwordlen;
  1461. {
  1462.     SA_PASSWD            passwd;
  1463.     SA_CHAR                buffer[512];
  1464.  
  1465.     if (sa_passwd_lookup(sactx, name, namelen, &passwd) != SA_SUCCEED)
  1466.     {
  1467.         sprintf(buffer, "MAIL login for user '%s' failed.", name);
  1468.         sa_log(sactx, buffer);
  1469.         return (SA_FAIL);
  1470.     }
  1471.  
  1472.     /* Verify the passwords are the same                                */
  1473.     if ((passwd.passwordlen != passwordlen) ||
  1474.         (strncmp(passwd.password, password, passwordlen) != 0))
  1475.     {
  1476.         /* Special case for anonymous user - NULL password match OK        */
  1477.         if ((namelen != 9) || (strncmp(name, "anonymous", 9) != 0))
  1478.         {
  1479.             sprintf(buffer, 
  1480.                 "MAIL login for user '%s' failed - bad password (%s)", 
  1481.                 name, password);
  1482.             sa_log(sactx, buffer);
  1483.             return (SA_FAIL);
  1484.         }
  1485.     }
  1486.  
  1487. #ifdef DEBUG
  1488.     sprintf(buffer, "MAIL User '%s' logged in.", name);
  1489.     sa_log(sactx, buffer);
  1490. #endif    /* DEBUG */
  1491.  
  1492.     return (SA_SUCCEED);
  1493. }
  1494.  
  1495. /*
  1496. **  TELNET_CONNECT
  1497. **
  1498. **    Process an Telnet Connect request. Verify the username/password against 
  1499. **    the Sambar Server password interfaces.
  1500. **
  1501. **  Parameters:
  1502. **    sactx            Sambar Server Application context to release.
  1503. **    saconn            Sambar Server User Connection handle.
  1504. **    username        Name of the user logging in.
  1505. **    usernamelen        Length of the user name
  1506. **    password        Password of the user logging in.
  1507. **    passwordlen        Length of the password.
  1508. **
  1509. **  Return Values:
  1510. **    SA_SUCCESS         Login Accepted.
  1511. **    SA_FAIL            Login Denied.
  1512. */
  1513. SA_RETCODE SA_PUBLIC
  1514. telnet_connect(sactx, name, namelen, password, passwordlen)
  1515. SA_CTX        *sactx;
  1516. SA_CHAR        *name;
  1517. SA_INT        namelen;
  1518. SA_CHAR        *password;
  1519. SA_INT        passwordlen;
  1520. {
  1521.     SA_PASSWD            passwd;
  1522.     SA_CHAR                buffer[512];
  1523.  
  1524.     if (sa_passwd_lookup(sactx, name, namelen, &passwd) != SA_SUCCEED)
  1525.     {
  1526.         sprintf(buffer, "Telnet login for user '%s' failed.", name);
  1527.         sa_log(sactx, buffer);
  1528.         return (SA_FAIL);
  1529.     }
  1530.  
  1531.     /* Verify the passwords are the same                                */
  1532.     if ((passwd.passwordlen != passwordlen) ||
  1533.         (strncmp(passwd.password, password, passwordlen) != 0))
  1534.     {
  1535.         /* Special case for anonymous user - NULL password match OK        */
  1536.         if ((namelen != 9) || (strncmp(name, "anonymous", 9) != 0))
  1537.         {
  1538.             sprintf(buffer, 
  1539.                 "Telnet login for user '%s' failed - bad password (%s)", 
  1540.                 name, password);
  1541.             sa_log(sactx, buffer);
  1542.             return (SA_FAIL);
  1543.         }
  1544.     }
  1545.  
  1546. #ifdef DEBUG
  1547.     sprintf(buffer, "Telnet User '%s' logged in.", name);
  1548.     sa_log(sactx, buffer);
  1549. #endif    /* DEBUG */
  1550.  
  1551.     return (SA_SUCCEED);
  1552. }
  1553.  
  1554. /*
  1555. **  GROUP_ADD
  1556. **
  1557. **    Add a new group
  1558. **
  1559. **  Parameters:
  1560. **    sactx        Sambar Server context
  1561. **    saconn        Sambar Server connection
  1562. **    saparams    RPC Parameters
  1563. **    infop        Error parameters
  1564. **
  1565. **  Returns:
  1566. **    SA_SUCCEED | SA_FAIL
  1567. */
  1568. SA_RETCODE SA_PUBLIC
  1569. group_add(sactx, saconn, saparams, infop)
  1570. SA_CTX        *sactx;
  1571. SA_CONN        *saconn;
  1572. SA_PARAMS    *saparams;
  1573. SA_INT        *infop;
  1574. {
  1575.     SA_CHAR        *data;
  1576.     SA_INT        datalen;
  1577.  
  1578.     if (sa_param(sactx, saparams, "groupname", &data, &datalen) != SA_SUCCEED)
  1579.     {
  1580.         *infop = SA_E_INVALIDDATA;
  1581.         sa_log(sactx, "group_add(): Expected parameter 'groupname'!");
  1582.         return (SA_FAIL);
  1583.     }
  1584.     
  1585.     if ((datalen == 0) || (datalen > SA_MAX_NAME))
  1586.     {
  1587.         *infop = SA_E_INVALIDDATA;
  1588.         sa_log(sactx, "group_add(): 'name' field left NULL!");
  1589.         return (SA_FAIL);
  1590.     }
  1591.  
  1592.     /* Can't create the group "other"                                    */
  1593.     if ((datalen == 5) && 
  1594.         (memcmp(data, SA_DEFAULT_GROUP, strlen(SA_DEFAULT_GROUP)) == 0))
  1595.     {
  1596.         *infop = SA_E_INVALIDDATA;
  1597.         sa_log(sactx, "group_add(): 'other' group already exists!");
  1598.         return (SA_FAIL);
  1599.     }
  1600.  
  1601.     if (sa_group_add(sactx, data, datalen) != SA_SUCCEED)
  1602.     {
  1603.         *infop = SA_E_ALREADYDEFINED;
  1604.         sa_log(sactx, "group_add(): sa_group_add() failed (already defined?)");
  1605.         return (SA_FAIL);
  1606.     }
  1607.  
  1608.     return (SA_SUCCEED);
  1609. }
  1610.  
  1611. /*
  1612. **  GROUP_DELETE
  1613. **
  1614. **    Delete an existing group
  1615. **
  1616. **  Parameters:
  1617. **    sactx        Sambar Server context
  1618. **    saconn        Sambar Server connection
  1619. **    saparams    RPC Parameters
  1620. **    infop        Error parameters
  1621. **
  1622. **  Returns:
  1623. **    SA_SUCCEED | SA_FAIL
  1624. **
  1625. **    Notes:
  1626. **    No users can belong to the group.
  1627. */
  1628. SA_RETCODE SA_PUBLIC
  1629. group_delete(sactx, saconn, saparams, infop)
  1630. SA_CTX        *sactx;
  1631. SA_CONN        *saconn;
  1632. SA_PARAMS    *saparams;
  1633. SA_INT        *infop;
  1634. {
  1635.     SA_INT        datalen;
  1636.     SA_CHAR        *data;
  1637.  
  1638.     if (sa_param(sactx, saparams, "groupname", &data, &datalen) != SA_SUCCEED)
  1639.     {
  1640.         *infop = SA_E_INVALIDDATA;
  1641.         sa_log(sactx, "group_delete(): Expected parameter 'groupname'!");
  1642.         return (SA_FAIL);
  1643.     }
  1644.  
  1645.     if ((datalen == 0) || (datalen > SA_MAX_NAME))
  1646.     {
  1647.         *infop = SA_E_INVALIDDATA;
  1648.         sa_log(sactx, "group_delete(): 'groupname' field left NULL!");
  1649.         return (SA_FAIL);
  1650.     }
  1651.  
  1652.     /* Can't delete the group "other"                                    */
  1653.     if ((datalen == 5) && 
  1654.         (memcmp(data, SA_DEFAULT_GROUP, strlen(SA_DEFAULT_GROUP)) == 0))
  1655.     {
  1656.         *infop = SA_E_INVALIDDATA;
  1657.         sa_log(sactx, "group_delete(): 'other' group cannot be deleted!");
  1658.         return (SA_FAIL);
  1659.     }
  1660.  
  1661.     /* Should only be allowed to do this if the group has no users.        */
  1662.     (SA_VOID)sa_group_delete(sactx, data, datalen);
  1663.  
  1664.     return (SA_SUCCEED);
  1665. }
  1666.  
  1667. /*
  1668. **  GROUP_SELECT
  1669. **
  1670. **    List all groups for selection.
  1671. **
  1672. **  Parameters:
  1673. **    sactx        Sambar Server context
  1674. **    saconn        Sambar Server connection
  1675. **    saparams    RPC Parameters
  1676. **    infop        Error parameters
  1677. **
  1678. **  Returns:
  1679. **    SA_SUCCEED | SA_FAIL
  1680. **
  1681. **  Notes:
  1682. **    This list is truncated at 100 names.
  1683. **    The group other always exists and is used for users with unrecognized
  1684. **    group names.
  1685. */
  1686. SA_RETCODE SA_PUBLIC
  1687. group_select(sactx, saconn, saparams, infop)
  1688. SA_CTX        *sactx;
  1689. SA_CONN        *saconn;
  1690. SA_PARAMS    *saparams;
  1691. SA_INT        *infop;
  1692. {
  1693.     SA_INT            i;
  1694.     SA_BOOL            found;
  1695.     SA_BOOL            selected;
  1696.     SA_INT            grouplen;
  1697.     SA_INT            userlen;
  1698.     SA_INT            numgroups;
  1699.     SA_CHAR            *user;
  1700.     SA_PASSWD        passwd;
  1701.     SA_CHAR            group[SA_MAX_NAME + 1];
  1702.     SA_GROUP        groups[100];
  1703.     SA_CHAR            buffer[512];
  1704.  
  1705.     /* If a name is provided make it SELECTED in the OPTION list        */
  1706.     userlen = 0;
  1707.     grouplen = 0;
  1708.     (SA_VOID)sa_param(sactx, saparams, "username", &user, &userlen);
  1709.  
  1710.     if (userlen > 0)
  1711.     {
  1712.         if (sa_passwd_lookup(sactx, user, userlen, &passwd) != SA_SUCCEED)
  1713.         {
  1714.             sprintf(buffer, "User lookup for '%s' failed.", user);
  1715.             sa_log(sactx, buffer);
  1716.             *infop = SA_E_INVALIDDATA;
  1717.             return (SA_FAIL);
  1718.         }
  1719.  
  1720.         grouplen = passwd.grouplen;
  1721.         if (grouplen > 0)
  1722.             memcpy(group, passwd.group, grouplen);
  1723.     }
  1724.  
  1725.     if (sa_group_list(sactx, groups, 100, &numgroups) != SA_SUCCEED)
  1726.     {
  1727.         sa_log(sactx, "group_select(): failure retrieving groups list!");
  1728.         return (SA_FAIL);
  1729.     }
  1730.  
  1731.     /* We could sort the names alphabetically at this point...            */
  1732.  
  1733.     /* Display the list of groups.                                        */
  1734.     found = 0;
  1735.     for (i = 0; i < numgroups; i++)
  1736.     {
  1737.         selected = 0;
  1738.         if ((grouplen > 0) &&
  1739.             (groups[i].namelen == grouplen) &&
  1740.             (memcmp(group, groups[i].name, grouplen) == 0))
  1741.         {
  1742.             selected = 1;
  1743.             found = 1;
  1744.         }
  1745.  
  1746.         sprintf(buffer, "<OPTION %s>%s\n", (selected ? "SELECTED" : ""),
  1747.             groups[i].name);
  1748.  
  1749.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1750.             return (SA_FAIL);
  1751.     }
  1752.  
  1753.     /* The group "other" always exists.                                    */
  1754.     sprintf(buffer, "<OPTION %s>%s\n", (found ? "" : "SELECTED"),
  1755.         SA_DEFAULT_GROUP);
  1756.     if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1757.         return (SA_FAIL);
  1758.  
  1759.     return (SA_SUCCEED);
  1760. }
  1761.  
  1762. /*
  1763. **  GROUP_LIST
  1764. **
  1765. **    List all groups for delete.
  1766. **
  1767. **  Parameters:
  1768. **    sactx        Sambar Server context
  1769. **    saconn        Sambar Server connection
  1770. **    saparams    RPC Parameters
  1771. **    infop        Error parameters
  1772. **
  1773. **  Returns:
  1774. **    SA_SUCCEED | SA_FAIL
  1775. **
  1776. **  Notes:
  1777. **    This list is truncated at 100 names.
  1778. **    The group "other" always exists and is the default group.
  1779. */
  1780. SA_RETCODE SA_PUBLIC
  1781. group_list(sactx, saconn, saparams, infop)
  1782. SA_CTX        *sactx;
  1783. SA_CONN        *saconn;
  1784. SA_PARAMS    *saparams;
  1785. SA_INT        *infop;
  1786. {
  1787.     SA_INT            i;
  1788.     SA_INT            numgroups;
  1789.     SA_GROUP        groups[100];
  1790.     SA_CHAR            buffer[512];
  1791.  
  1792.     if (sa_group_list(sactx, groups, 100, &numgroups) != SA_SUCCEED)
  1793.     {
  1794.         sa_log(sactx, "group_list(): failure retrieving groups list!");
  1795.         return (SA_FAIL);
  1796.     }
  1797.  
  1798.     /* We could sort the list alphabetically at this point.                */
  1799.  
  1800.     /* Display the list of groups.                                        */
  1801.     for (i = 0; i < numgroups; i++)
  1802.     {
  1803.         sprintf(buffer, 
  1804.             "<A HREF=\"/session/delgroup?groupname=%s&RCpage=/sysadmin/usermgmt/grplist.stm\" onClick=\"return confirmDelete()\"><IMG border=0 HEIGHT=20 WIDTH=20 SRC=\"/sysimage/system/trash.gif\"></A> %s<BR>\n",
  1805.             groups[i].name, groups[i].name);
  1806.  
  1807.         if (sa_conn_send(saconn, buffer, SA_NULLTERM) != SA_SUCCEED)
  1808.             return (SA_FAIL);
  1809.     }
  1810.  
  1811.     return (SA_SUCCEED);
  1812. }
  1813.