home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netusfun.zip / userapi.c
C/C++ Source or Header  |  2003-03-04  |  100KB  |  2,521 lines

  1. /*******************************************************************************/
  2. /* SCCSID: %W% %E%                                                             */
  3. /*                                                                             */
  4. /*                                                                             */
  5. /* OCO Source Materials                                                        */
  6. /*                                                                             */
  7. /* Program number 5639-F93                                                     */
  8. /*                                                                             */
  9. /* (c) Copyright IBM Corp. 1987,1999                                           */
  10. /*                                                                             */
  11.                                                         */
  12. /*                                                                             */
  13. /*******************************************************************************/
  14. /*
  15.  * (C) 1994 IBM Corporation
  16.  * (P) 1994 IBM OS/2 LAN Server
  17.  *
  18.  * OCO Source Materials
  19.  */
  20.  
  21.  
  22. /*     Post ISO/CMVC Revision history:
  23.  *
  24.  *  Flags prefix: f = feature d = defect
  25.  *
  26.  *  Flag       Fixer         Date     Tester     Date    Review Date    Release
  27.  *  ----      --------     --------  -------   --------  -----------   ---------
  28.  * @f00 f2175  TRK        93Dec09     TRK     93Dec09     93Dec11      ls 4.0
  29.  * @d01 d6634  SYED       3-28-94
  30.  * d4701       SL         02jun94
  31.  * d9983       MEB        94Jul22     MEB     94Jul22     94Jul25      ls 4.0
  32.  * d33038      VEC        96Mar03     VEC     96Mar03     96Mar03      ls 4.0
  33.  *
  34.  * DESCRIPTIONS:
  35.  * f2175:
  36.  *         WUserPasswordSet3 changes.
  37.  * d6634:
  38.  *         Update last logon and last logoff in UserSetInfo.
  39.  * d4701:
  40.  *         Stop checking for (unsigned variables < 0).
  41.  * d9983:
  42.  *         Add the ability to set the primary computer name in the
  43.  *         UserModalsSet level 101.
  44.  *
  45.  ******************************************************************************
  46.  * *********  CHANGE HISTORY **************************************************
  47.  *
  48.  * Defect  Flag   Fixer   Date      Description
  49.  * ------  -----  ------  --------  ---------------------------------------
  50.  * 42799   @D05   JGC     12/12/96  Removethe change of d33038. It did no
  51.  *                                  work.  Remove the change makes it work.
  52.  * d43314  @D06   JGC     01/24/97  Remove the change of d42799, i.e., put
  53.  *                                  back of d33038 fix.
  54.  * d43122  @D07   rcf     03/14/97  Detect change to null password
  55.  *
  56.  * f55952  @f08   lc      07/07/99  Changes to support Domain Wide UID feature
  57.  */
  58.  
  59. /*
  60.  ******************************************************************************
  61.  *      USERAPI.C       Second level functions for NetUser APIs
  62.  *
  63.  *      The interface in this module should be same as defined
  64.  *      in summary.api except that it is purely local
  65.  *      (Thus there is no servername parameter).
  66.  *
  67.  *      Functions:
  68.  *              UAdd, UserAdd
  69.  *              UserGetGroups
  70.  *              UserSetGroups
  71.  *              UserValidate, UserValidate2
  72.  *              UserPasswordSet
  73.  *              UserGetInfo
  74.  *              UserSetInfo
  75.  *              UserDel
  76.  *              UserEnum
  77.  *              UserGetModals
  78.  *              UserSetModals
  79.  *
  80.  *      History:
  81.  *
  82.  *      10/6/87     HongLy  Changes in  NetPackString
  83.  *                           1. Do a NetPackString in order
  84.  *                           2. Do not put a NULL pointer in variable length
  85.  *                              instead put a pointer to '\0';
  86.  *      12/6/87     HongLy  add script
  87.  *
  88.  *      10/17/88    Pradym  Many changes and additions to conform to LM1.2
  89.  *      01/25/89    Pradym  Moved bunch of lower level functions to uasutil.c
  90.  *
  91.  *
  92.  *      WARNING:
  93.  *                  A File Semaphore has been added (LOCKDBFILE,
  94.  *                  UNLOCKDBFILE) IT IS NECESSARY TO GRAB THIS FIRST
  95.  *                  BEFORE GRABBING MEMORY SEMAPHORE.
  96.  *                  Memory semaphore must be released before doing DISK I/O.
  97.  *
  98.  */
  99.  
  100. #define  INCL_DOSMEMMGR
  101. #define  INCL_DOSFILEMGR
  102. #define  INCL_DOSSEMAPHORES
  103. #define  INCL_DOSERRORS
  104. #define  INCL_DOSPROCESS
  105. #include <os2.h>
  106.  
  107. #include <ctype.h>
  108. #include <netcons.h>
  109. #include <icanon.h>
  110. #include <dos.h>
  111. #include <netlib.h>
  112. #include <neterr.h>
  113. #include <shares.h>
  114. #include <apiutil.h>
  115. #include <inetapi.h>
  116. #include <remutil.h>
  117. #include <rdrioctl.h>   /* next three are required for srvinfo.h */
  118. #include <ncb.h>
  119. #include <netbuf.h>
  120. #include <server.h>
  121. #include <wksta.h>
  122. #include <api.h>        /* GetServerSegs & FreeServerSegs */
  123. #include <resstats.h>
  124. #include <srvinfo.h>
  125. #include <access.h>
  126. #include <uascache.h>
  127. #include <apisec.h>
  128. #include <rnetapi.h>
  129. #include <crypt.h>
  130. #include <permit.h>
  131. #include <acfproto.h>
  132. #include <assert.h>
  133. #include "uasutil.h"
  134.  
  135.  
  136. API_FUNCTION FreeUserEntries(char far * username);
  137.  
  138. /*
  139.  *      Local prototype
  140. */
  141. static int near vcopy(char far *, char far *, int);
  142. unsigned short  SetHomeDir(unsigned short, char far *, char far *, unsigned short);
  143. unsigned short  SetScriptPath(char far *, char far *, unsigned short);
  144.  
  145. /*
  146.  *      UAdd -- Add a user name
  147.  *
  148.  *      Following default values are used for level 1 calls.
  149.  *
  150.  *              full_name       usri1_name
  151.  *              usr_comment     NULL
  152.  *              workstations    NULL (means login allowed from any)
  153.  *              acct_expires    TIMEQ_FOREVER (never expires)
  154.  *              max_storage     USER_MAXSTORAGE_UNLIMITED
  155.  *              logon_hours     Always
  156.  *              logon_server    Domain Controller  (Null_String)
  157.  *
  158.  *      Array containing old passwords for history checking is initialized
  159.  *      to all 0xFFs in user record being added. The units_per_week is
  160.  *      UNITS_PER_WEEK for this release and user passed parameter in struct
  161.  *      user_info_2, if any, is ignored.
  162.  *
  163.  *      Input:
  164.  *              buf     filled with struct user_info_X (X = Level)
  165.  *              buflen  size of buffer
  166.  *              level   level of detail (must be 1 or 2)
  167.  *              home    homedirectory
  168.  *              script  logon script
  169.  *              fd      net.acc file handle
  170.  *
  171.  *      Output:
  172.  *              0 -- success
  173.  *              NERR_GroupExists
  174.  *              NERR_ACFNoRoom
  175.  *              NERR_UserExists
  176.  *              NERR_FileIOFail
  177.  *
  178.  */
  179. int
  180. UAdd(buf, level, home, script, fd)
  181. char far *buf;
  182. short level;
  183. char far *home;
  184. char far *script;
  185. int fd;
  186. {
  187. #ifndef REMONLY
  188.         int err;
  189.         struct user_object far *uo;
  190.         struct _userrec far *u;
  191.         char       priv;
  192.         char far * name;
  193.         char far * passwd;
  194.         char far * comment;
  195.         char far * buf_end;
  196.         SEL        sel;
  197.         unsigned short full=TRUE;                                        /* @f08a */
  198.         unsigned short flags;
  199.         unsigned long type;
  200.         char far * p;
  201.         long pos;
  202.         long serial;
  203.         char local_uname[UNLEN+1];
  204.  
  205.         if (level == LEVEL_1)
  206.                 name = ((struct user_info_1 far *)buf)->usri1_name;
  207.         else
  208.                 name = ((struct user_info_2 far *)buf)->usri2_name;
  209.  
  210.         if (err = I_NetNameCanonicalize(NULL, name, (char far *)local_uname,
  211.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  212.             return ERROR_INVALID_PARAMETER;
  213.  
  214.         name = local_uname;
  215.  
  216.         /* Is name in group list */
  217.         if (GroupId(name, &serial) >= 0 )       /* name exists */
  218.                 return NERR_GroupExists;
  219.  
  220.         if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
  221.                 return err;
  222.         else {
  223.                 uo = (struct user_object far *) PTR(sel, 0);
  224.                 u = &uo->uo_record;
  225.                 buf_end = (char far *)(u + 1);
  226.         }
  227.  
  228.         if (Ucb->hdr.num_users >= MAX_USERS)
  229.                 err = NERR_ACFNoRoom;
  230.         else
  231.             err = GetUserObject(fd, name, uo, &pos);
  232.  
  233.         if (err == 0)                   /* Duplicate Name */
  234.              err = NERR_UserExists;
  235.  
  236.         if (err != NERR_UserNotFound)
  237.                 {
  238.                     DosFreeSeg(sel);
  239.                     return err;
  240.                 }
  241.  
  242.         /* zero the "err" variable so we won't be bitten unwittingly */
  243.         err = 0;
  244.  
  245.         /* Ok ! no duplicate, copy the stuff into the u record */
  246.         u->name[UNLEN] = '\0';
  247.         strncpyf(u->name, name, UNLEN);
  248.  
  249.         /* common defaults for both levels */
  250.         u->last_logon = u->last_logoff = 0L;    /*  0 ==> unknown */
  251.         u->bad_pw_count = u->num_logons = -1;   /* -1 ==> unknown */
  252.         u->code_page = 0;
  253.         memsetf(u->logonhrs, (unsigned char) 0xFF, UNITS_PER_WEEK/8);
  254.         memsetf(u->old_passwds, (unsigned char) 0xFF,sizeof(u->old_passwds));
  255.         if (level == LEVEL_1)
  256.                 {
  257.                 passwd = ((struct user_info_1 far *)buf)->usri1_password;
  258.                 priv = (char) ((struct user_info_1 far *)buf)->usri1_priv;
  259.                 flags = ((struct user_info_1 far *)buf)->usri1_flags;
  260.                 comment = ((struct user_info_1 far *)buf)->usri1_comment;
  261.                 /* set defaults */
  262.                 URAppend (u, &buf_end, &u->full_name_o, name, MAXCOMMENTSZ,
  263.                         FALSE);
  264.                 URAppend (u, &buf_end, &u->usr_comment_o, NULL, 0, FALSE);
  265.                 URAppend (u, &buf_end, &u->parms_o, NULL, 0, FALSE);
  266.                 URAppend (u, &buf_end, &u->workstation_o, NULL, 0, FALSE);
  267.                 /* default logon_server is "" ==> domain controller */
  268.                 URAppend (u, &buf_end, &u->logon_server_o, NULL, 0, FALSE);
  269.                 u->acct_expires = TIMEQ_FOREVER;
  270.                 u->max_storage  = USER_MAXSTORAGE_UNLIMITED;
  271.                 u->user.uc0_auth_flags = 0;
  272.                 u->country_code = 0;
  273.                 u->code_page = 0;
  274.                 GetCountryCode((unsigned short far *) &u->country_code);
  275.         }
  276.         else
  277.                 {
  278.                 passwd = ((struct user_info_2 far *)buf)->usri2_password;
  279.                 priv = (char) ((struct user_info_2 far *)buf)->usri2_priv;
  280.                 flags = ((struct user_info_2 far *)buf)->usri2_flags;
  281.                 comment = ((struct user_info_2 far *)buf)->usri2_comment;
  282.  
  283.                 /* set level 2 stuff */
  284.                 if (((struct user_info_2 far *)buf)->usri2_full_name == NULL)
  285.                     URAppend(u, &buf_end, &u->full_name_o, NULL, 0, FALSE);
  286.                 else
  287.                     URAppend(u, &buf_end, &u->full_name_o,
  288.                         ((struct user_info_2 far *)buf)->usri2_full_name,
  289.                         MAXCOMMENTSZ, FALSE);
  290.                 if (((struct user_info_2 far *)buf)->usri2_usr_comment == NULL)
  291.                         URAppend(u, &buf_end, &u->usr_comment_o,
  292.                                  NULL, 0, FALSE);
  293.                 else
  294.                         {
  295.                         URAppend(u, &buf_end, &u->usr_comment_o,
  296.                              ((struct user_info_2 far *)buf)->usri2_usr_comment,
  297.                               MAXCOMMENTSZ, FALSE);
  298.                 }
  299.                 if (((struct user_info_2 far *)buf)->usri2_parms == NULL)
  300.                         URAppend(u, &buf_end, &u->parms_o, NULL, 0, FALSE);
  301.                 else
  302.                         URAppend(u, &buf_end, &u->parms_o,
  303.                              ((struct user_info_2 far *)buf)->usri2_parms,
  304.                               MAXCOMMENTSZ, FALSE);
  305.  
  306.                 u->acct_expires =
  307.                         ((struct user_info_2 far *)buf)->usri2_acct_expires;
  308.                 u->max_storage =
  309.                         ((struct user_info_2 far *)buf)->usri2_max_storage;
  310.                 /* space delimited computer names terminated by \0 */
  311.                 if (((struct user_info_2 far *)buf)->usri2_workstations != NULL)
  312.                         {
  313.                         p = ((struct user_info_2 far *)buf)->usri2_workstations;
  314.                         err = URAppend (u, &buf_end, &u->workstation_o, p,
  315.                                 MAXWORKSTATIONS * (CNLEN+1), TRUE);
  316.                 }
  317.                 else
  318.                         URAppend (u, &buf_end, &u->workstation_o, NULL, 0, FALSE);
  319.                 /* logon_hours == NULL ==> Access allowed at All times */
  320.                 p = ((struct user_info_2 far *)buf)->usri2_logon_hours;
  321.                 if ( p != NULL )
  322.                     memcpyf(u->logonhrs, p, UNITS_PER_WEEK/8);
  323.                 /* set the logon server if given. NULL ==> domain controller */
  324.                 /* Note that \\* means any server can be used as logon server */
  325.                 p = ((struct user_info_2 far *)buf)->usri2_logon_server;
  326.                 if (p != NULL && p[0] != '\0')
  327.                     {
  328.                     if (p[0] == '\\' && p[1] == '\\' && p[2] == '*' && strlenf(p) == 3)
  329.                         URAppend(u, &buf_end,&u->logon_server_o,p,UNCLEN,FALSE);
  330.                     else if ( I_NetPathType(NULL, p, &type, 0L) ||
  331.                                               type != ITYPE_UNC_COMPNAME)
  332.                         err = ERROR_INVALID_PARAMETER;
  333.                     else
  334.                         URAppend(u, &buf_end,&u->logon_server_o,p,UNCLEN,FALSE);
  335.                 }
  336.                 else
  337.                     URAppend(u, &buf_end, &u->logon_server_o, NULL, 0, FALSE);
  338.                 u->country_code = ((struct user_info_2 far *)buf)->usri2_country_code;
  339.                 u->code_page = ((struct user_info_2 far *)buf)->usri2_code_page;
  340.                 u->user.uc0_auth_flags = ((struct user_info_2 far *)buf)->usri2_auth_flags;
  341.         }
  342.  
  343.         if (err)
  344.             {
  345.             DosFreeSeg(sel);
  346.             return err;
  347.         }
  348.  
  349.         if (UseEncryption) {
  350.                                         /* encrypted password */
  351.                 if (err = CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, passwd, u->passwd))
  352.                     {
  353.                     DosFreeSeg(sel);
  354.                     return(err);
  355.                 }
  356.         }
  357.         else
  358.                                         /* plain text password */
  359.                 memcpyf(u->passwd, passwd, PWLEN + 1);
  360.  
  361.         u->user.uc0_priv = priv;
  362.  
  363.         if (home != NULL)
  364.                 URAppend (u, &buf_end, &u->directory_o, home, PATHLEN, FALSE);
  365.         else
  366.                 URAppend (u, &buf_end, &u->directory_o, NULL, 0, FALSE);
  367.  
  368.         if (comment != NULL)
  369.                 URAppend (u, &buf_end, &u->comment_o, comment, MAXCOMMENTSZ, FALSE);
  370.         else
  371.                 URAppend (u, &buf_end, &u->comment_o, NULL, 0, FALSE);
  372.  
  373.         if (script != NULL)
  374.                 URAppend (u, &buf_end, &u->script_o, script, PATHLEN, FALSE);
  375.         else
  376.                 URAppend (u, &buf_end, &u->script_o, NULL, 0, FALSE);
  377.  
  378.         /* Warning: bit0 must be 1 for this release, enforced by UI */
  379.         u->flags = flags;
  380.         u->last = time_now();
  381.         memsetf(u->user.uc0_groups, 0, sizeof(u->user.uc0_groups));
  382.  
  383.         /* level 200 add uses the supplied serial number as opposed   */ /* @f08a */
  384.         /* to the next available one from the hash table. Also, set   */ /* @f08a */
  385.         /* full flag to indicate serial number supplied is to be used */ /* @f08a */
  386.  
  387.         if (level == LEVEL_200)                                          /* @f08a */
  388.         {                                                                /* @f08a */
  389.            u->user.uc0_guid.guid_serial =                                /* @f08a */
  390.                 ((struct user_info_200 far *)buf)->usri200_serial;       /* @f08a */
  391.            full = FULL_USE_SERIAL;                                       /* @f08a */
  392.         }                                                                /* @f08a */
  393.         else                                                             /* @f08a */
  394.         {                                                                /* @f08a */
  395.            u->user.uc0_guid.guid_serial =
  396.                 UserHashTbl[u->user.uc0_guid.guid_uid].uh_serial;
  397.         }                                                                /* @f08a */
  398.  
  399.         /* before writing the record on disk zero the 10 resvd bytes of GUID */
  400.         memsetf(u->user.uc0_guid.guid_rsvd, 0, 10);
  401.  
  402.         u->size = (char far *)buf_end - (char far *)u;
  403.  
  404.         /* mark its membership in one of the special groups */
  405.         if (uo->uo_record.user.uc0_priv == USER_PRIV_ADMIN)
  406.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->AdminsId);
  407.         else if (uo->uo_record.user.uc0_priv == USER_PRIV_GUEST)
  408.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->GuestsId);
  409.         else if (uo->uo_record.user.uc0_priv == USER_PRIV_USER)
  410.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->UsersId);
  411.  
  412.         pos = 0L;
  413.         if (err = WriteUserObject (fd, &pos, uo, full))                  /* @f08c */
  414.                 {
  415.                 DosFreeSeg(sel);
  416.                 return err;
  417.         }
  418.  
  419.         Ucb->usercnt++;
  420.  
  421.         DosFreeSeg(sel);
  422.         return 0;
  423. #else
  424.         return ERROR_NOT_SUPPORTED;
  425. #endif  /* REMONLY */
  426.  
  427.         /* quiet the compiler */
  428.         if(buf || level || home || script || fd);
  429. }
  430.  
  431. /*
  432.  *      UserAdd -- Adding a user
  433.  *
  434.  *      Since this is mostly a file-IO, we would not memory seg unless
  435.  *      it is necessary
  436.  *
  437.  *      Input:
  438.  *              buf         struct user_info_1 or user_info_2
  439.  *              rootdir     path (relative/abs) for home_dir
  440.  *              level       level of info being supplied
  441.  *
  442.  *      Output:
  443.  *              NERR_Success ( 0 )
  444.  *              ERROR_INVALID_LEVEL
  445.  *              NERR_BufTooSmall
  446.  *              NERR_UserExists
  447.  *              NERR_GroupExists
  448.  *              NERR_ACFNoRoom
  449.  *              NERR_ACFFileIOFail
  450.  */
  451. int
  452. UserAdd(buf, rootdir, level)
  453. char far *buf;
  454. char far *rootdir;
  455. short level;
  456. {
  457. #ifndef REMONLY
  458.         int err = 0;
  459.         int fd;
  460.         char homedir[PATHLEN+1];
  461.         char script[PATHLEN+1];
  462.         char far * name;
  463.         char far * home_dir;
  464.         char far * scriptp;
  465.         struct user_info_1 far *user = (struct user_info_1 far *)buf;
  466.         struct user_info_2 far *user2 = (struct user_info_2 far *)buf;
  467.         char            tmp[MAXWORKSTATIONS * (CNLEN+1)];
  468.         unsigned short  count;
  469.         unsigned short  flags;
  470.         char far * workstn;
  471.  
  472.  
  473.         if (level == LEVEL_1)
  474.                 name = ((struct user_info_1 far *)buf)->usri1_name;
  475.         else
  476.                 name = ((struct user_info_2 far *)buf)->usri2_name;
  477.  
  478.         /* Validate the user name */
  479.         if (I_NetNameValidate(NULL, name, NAMETYPE_USER, 0L) )
  480.                 return NERR_BadUsername;
  481.  
  482.         /* Validate the data */
  483.         if (err = ValidateUser(buf, level) )
  484.                 return err;
  485.  
  486.         if (level == LEVEL_1)
  487.                 {
  488.                 home_dir = ((struct user_info_1 far *)buf)->usri1_home_dir;
  489.                 scriptp = ((struct user_info_1 far *)buf)->usri1_script_path;
  490.                 flags = ((struct user_info_1 far *)buf)->usri1_flags;
  491.         }
  492.         else
  493.                 {
  494.                 home_dir = ((struct user_info_2 far *)buf)->usri2_home_dir;
  495.                 scriptp = ((struct user_info_2 far *)buf)->usri2_script_path;
  496.                 flags = ((struct user_info_2 far *)buf)->usri2_flags;
  497.                 workstn = ((struct user_info_2 far *)buf)->usri2_workstations;
  498.         }
  499.  
  500.         if ( ((level == LEVEL_2) || (level == LEVEL_200)) && workstn != NULL )  /* @f08c */
  501.             {
  502.             if (strlenf(workstn) > MAXWORKSTATIONS *(CNLEN+1))
  503.                 return ERROR_INVALID_PARAMETER;
  504.             strcpyf(tmp, workstn);
  505.             if (I_NetListCanonicalize(NULL,
  506.                                       tmp,
  507.                                       LIST_DELIMITER_STR_API,
  508.                                       workstn,
  509.                                       strlenf(workstn)+1,
  510.                                       &count,
  511.                                       NULL,
  512.                                       0,
  513.                                       NAMETYPE_COMPUTER|OUTLIST_TYPE_API|
  514.                                       INLC_FLAGS_CANONICALIZE) ||
  515.                                       (count > MAXWORKSTATIONS))
  516.                 {
  517.                 strcpyf(workstn, tmp);
  518.                 return ERROR_INVALID_PARAMETER;
  519.             }
  520.         }
  521.  
  522.         if ( !(err = SetHomeDir(flags, home_dir, homedir, sizeof(homedir))) )
  523.             err = SetScriptPath(scriptp, script, sizeof(script));
  524.  
  525.         if (err == NERR_Success)
  526.                 {
  527.                 if ((err = OpenAccount(&fd)) == NERR_Success)
  528.                     {
  529.                     /* add a new user record */
  530.                     LOCKDBFILE();
  531.                     LOCKUSEG();
  532.                     err = UAdd(buf, level, homedir, script, fd);
  533.                     UNLOCKUSEG();
  534.                     UNLOCKDBFILE();
  535.                     CloseAccount(fd);
  536.                 }
  537.         }
  538.         /* restore workstation list */
  539.         if ( ((level == LEVEL_2) || (level == LEVEL_200)) && workstn != NULL ) /* @f08c */
  540.                 strcpyf(workstn, tmp);
  541.  
  542.         return err;
  543. #else
  544.         return ERROR_NOT_SUPPORTED;
  545. #endif  /* REMONLY */
  546.  
  547.         /* quiet the compiler */
  548.         if (buf || rootdir || level)
  549.             ;
  550. }
  551.  
  552. /*
  553.  *      UserGetGroups -- Get All groups name the user belongs to
  554.  *
  555.  *      Input:
  556.  *              Uname -- user name
  557.  *              level -- level of detail
  558.  *              buf
  559.  *              buflen -- length of  buffer
  560.  *
  561.  *      Output:
  562.  *              entries -- number of entries in returned buffer
  563.  *              total -- number of entries available
  564.  *
  565.  *      Returns:
  566.  *              0 -- success
  567.  *              NERR_ACFFileIOFail
  568.  *              ERROR_INVALID_LEVEL
  569.  *              NERR_BufTooSmall
  570.  *              ERROR_MORE_DATA
  571.  *              NERR_UserNotFound
  572.  */
  573. int
  574. UserGetGroups(uname,  buf, buflen, entries, total)
  575. const char far *uname;
  576. char far *buf;
  577. unsigned short buflen;
  578. unsigned short far *entries;
  579. unsigned short far *total;
  580. {
  581. #ifndef REMONLY
  582.         struct user_object far *uo;
  583.         SEL     sel;
  584.         int err = 0;
  585.         int fd;
  586.         int avail;
  587.         char far *group;
  588.         char local_uname[UNLEN+1];
  589.         int i;
  590.         int j;
  591.         char c;
  592.         long pos;
  593.  
  594.  
  595.         if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
  596.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  597.             return NERR_UserNotFound;
  598.  
  599.         if (err = OpenAccount(&fd))
  600.             return err;
  601.  
  602.         if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
  603.             {
  604.             CloseAccount(fd);
  605.             return err;
  606.         }
  607.         else
  608.                 {
  609.                 uo = (struct user_object far *) PTR(sel, 0);
  610.                 LOCKDBFILE();
  611.                 err = GetUserObject(fd, (char far *)local_uname, uo, &pos);
  612.                 if (!err)
  613.                         group = uo->uo_record.user.uc0_groups;
  614.                 UNLOCKDBFILE();
  615.         }
  616.  
  617.         if (err)
  618.                 {
  619.                 CloseAccount(fd);
  620.                 DosFreeSeg(sel);
  621.                 return err;
  622.         }
  623.  
  624.         /* group is ptr to the group bit map let's enumerate it */
  625.  
  626.         *entries =0;
  627.         *total = 0;
  628.         avail = buflen/sizeof(struct group_info_0);
  629.         for (i=0; i < MAXGROUP/8; i++ )
  630.                 {
  631.                 c = group[i];
  632.                 for (j=0; j < 8; j++, c >>= 1 )
  633.                         if (c & 1) {    /* True */
  634.                             //    ASSERT((c = Ucb->group[i*8+j].name[0]) != REC_DELETE
  635.                             //    && c != REC_EMPTY, nprintf("Internal bug 3\n"))
  636.  
  637.                                 if (avail > 0) {
  638.                                         memcpyf(buf, (char far *)&Ucb->group[i*8+j]
  639.                                                 , sizeof(struct group_info_0) );
  640.                                         buf += sizeof(struct group_info_0);
  641.                                         avail --;
  642.  
  643.                                         (*entries)++;
  644.                                 }
  645.                                 (*total)++;
  646.                         }
  647.         }
  648.  
  649.         CloseAccount(fd);
  650.         DosFreeSeg(sel);
  651.         if (*total > *entries)
  652.                 return ERROR_MORE_DATA;
  653.         else
  654.                 return NERR_Success;
  655. #else
  656.         return ERROR_NOT_SUPPORTED;
  657. #endif  /* REMONLY */
  658.  
  659.         /* quiet the compiler */
  660.         if (uname || buf || buflen || entries || total);
  661. }
  662.  
  663. /*
  664.  *      UserSetGroups   Replace existing group map  of the named user
  665.  *                      with a new one making this user member of groups
  666.  *                      specified in buffer.
  667.  *
  668.  *      Input:
  669.  *              uname       user name
  670.  *              level       level of detail
  671.  *              buf         Buffer filled with struct group_info_0
  672.  *              buflen      length of  buffer
  673.  *              entries     number of entries in supplied buffer
  674.  *
  675.  *      Output:
  676.  *
  677.  *
  678.  *      Returns:
  679.  *              0 -- success
  680.  *              NERR_ACFFileIOFail
  681.  *              ERROR_INVALID_LEVEL
  682.  *              NERR_BufTooSmall
  683.  *              ERROR_MORE_DATA
  684.  *              NERR_UserNotFound
  685.  */
  686. int
  687. UserSetGroups(uname,  buf, buflen, entries)
  688. const char far *uname;
  689. char far *buf;
  690. unsigned short buflen;
  691. unsigned short entries;
  692. {
  693. #ifndef REMONLY
  694.         struct user_object far *uo;
  695.         SEL       sel;
  696.         struct group_info_0 far * gname;
  697.         int err = 0;
  698.         USER far * user;
  699.         short gid;
  700.         int fd;
  701.         long pos;
  702.         char local_uname[UNLEN+1];
  703.  
  704.  
  705.         if ( (buflen/sizeof(struct group_info_0)) < entries )
  706.                 return NERR_BufTooSmall;
  707.  
  708.         if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
  709.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  710.             return NERR_UserNotFound;
  711.  
  712.         if (err = OpenAccount(&fd))
  713.             return err;
  714.  
  715.         if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
  716.             {
  717.             CloseAccount(fd);
  718.             return err;
  719.         }
  720.         else
  721.                 uo = (struct user_object far *) PTR(sel, 0);
  722.  
  723.         LOCKDBFILE();
  724.         if (err = GetUserObject(fd, (char far *)local_uname, uo, &pos))
  725.                 {
  726.                 UNLOCKDBFILE();
  727.                 CloseAccount(fd);
  728.                 DosFreeSeg(sel);
  729.                 return err;
  730.         }
  731.  
  732.         memsetf(uo->uo_record.user.uc0_groups, 0,
  733.                         sizeof(uo->uo_record.user.uc0_groups));
  734.  
  735.         gname = (struct group_info_0 far *) buf;
  736.  
  737.         /* now prepare new map */
  738.         while( entries-- )
  739.                 {
  740.                 if (err = I_NetNameCanonicalize(NULL, gname->grpi0_name,
  741.                         (char far *)gname->grpi0_name,
  742.                         GNLEN+1, NAMETYPE_GROUP, 0L))
  743.                 {
  744.                         /* treat bad name same as Group not found */
  745.                     err = NERR_GroupNotFound;
  746.                 }
  747.                 else if (!(GetGroupId(Ucb->group, gname->grpi0_name, &gid)))
  748.                     {
  749.                     /* return error if Special Group found */
  750.                     if ((gid != Ucb->AdminsId) &&
  751.                         (gid != Ucb->GuestsId) &&
  752.                         (gid != Ucb->LocalId) &&
  753.                         (gid != Ucb->UsersId))
  754.                             MARKUSE(uo->uo_record.user.uc0_groups, gid);
  755.                     else
  756.                             err = NERR_SpeGroupOp;
  757.                 }
  758.                 else
  759.                     err = NERR_GroupNotFound;
  760.  
  761.                 if (err)
  762.                     {
  763.                     UNLOCKDBFILE();
  764.                     CloseAccount(fd);
  765.                     DosFreeSeg(sel);
  766.                     return err;
  767.                 }
  768.                 gname++;
  769.         }
  770.         /* mark its membership in one of the special groups */
  771.         if (uo->uo_record.user.uc0_priv == USER_PRIV_ADMIN)
  772.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->AdminsId);
  773.         else if (uo->uo_record.user.uc0_priv == USER_PRIV_GUEST)
  774.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->GuestsId);
  775.         else if (uo->uo_record.user.uc0_priv == USER_PRIV_USER)
  776.                 MARKUSE(uo->uo_record.user.uc0_groups, Ucb->UsersId);
  777.  
  778.         err = WriteUserObject (fd, &pos, uo, TRUE);
  779.  
  780.         LOCKUSEG();
  781.         user = FindUidInCache (uo->uo_record.user.uc0_guid.guid_uid,
  782.                                 uo->uo_record.user.uc0_guid.guid_serial);
  783.         if ( err == 0 && user)
  784.             {
  785.             /* update the cache */
  786.             memcpyf(user->uc0_groups, uo->uo_record.user.uc0_groups,
  787.                 sizeof(user->uc0_groups));
  788.             KickPinballSem();
  789.         }
  790.         UNLOCKUSEG();
  791.  
  792.         UNLOCKDBFILE();
  793.         DosFreeSeg(sel);
  794.         CloseAccount(fd);
  795.         return err;
  796. #else
  797.         return ERROR_NOT_SUPPORTED;
  798. #endif  /* REMONLY */
  799.  
  800.         /* quiet the compiler */
  801.         if (uname || buf || buflen || entries);
  802. }
  803.  
  804.  
  805. /*
  806.  *      UserPasswordSet
  807.  *
  808.  *      passlen     password length (when it was in plain text form)
  809.  */
  810. int
  811. UserPasswordSet(uname, old, new, passlen, uo, pos, fd, clevel)
  812. char far *uname;
  813. char far *old;          /* old password */
  814. char far *new;          /* new password */
  815. unsigned short   passlen;
  816. struct user_object far *uo;
  817. long far * pos;
  818. int fd;
  819. unsigned short   clevel;
  820. {
  821. # define NULL_ESTD "\xaa\xd3\xb4\x35\xb5\x14\x04\xee\xaa\xd3\xb4\x35\xb5\x14\x04\xee" /*@D07*/
  822. #ifndef REMONLY
  823.         struct _userrec far *u;
  824.         register int err = 0;
  825.         unsigned long current_time;
  826.         int saverr = 0;
  827.         int nullpw = FALSE;                                              /*@D07*/
  828.         u = &uo->uo_record;
  829.  
  830.         if (memcmpf(NULL_ESTD, new, ENCRYPTED_PWLEN)) nullpw = FALSE;    /*@D07*/
  831.         else nullpw = TRUE;               /*New PW is NULL*/             /*@D07*/
  832.         if /* this is NOT from a remote call to WUserPasswordSet3 */
  833.           (old)                         // @f00a
  834.           {
  835.  
  836.           if (UseEncryption)
  837.               {
  838.               /* encrypting server, determine if it has the right  */
  839.               if (CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, old, old))
  840.                       return ERROR_ACCESS_DENIED;
  841.               else  if (memcmpf(u->passwd, old, ENCRYPTED_PWLEN))
  842.                       saverr = ERROR_INVALID_PASSWORD;
  843.               else  if (CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, new, new))
  844.                       return ERROR_ACCESS_DENIED;
  845.               }
  846.           else
  847.               {
  848.               /* non encrypting server */
  849.               if (strncmpf(u->passwd, old, PWLEN + 1))
  850.                   saverr = ERROR_INVALID_PASSWORD;
  851.               }
  852.           }
  853.         else  // @f00a
  854.           {
  855.           if (UseEncryption  &&
  856.               CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, new, new))
  857.             return ERROR_ACCESS_DENIED;
  858.           }
  859.  
  860.         current_time = time_now();
  861.         /*
  862.          * Bypass all restrictions when called from NETLOGON service.
  863.         */
  864.         if (clevel != ACCESS_NETLOGON)
  865.             {
  866.             if ((unsigned long)(u -> acct_expires) < current_time)
  867.                 return NERR_AccountExpired;
  868.  
  869.             if (!(u->flags & UF_PASSWD_NOTREQD))        // password is required
  870.                 {
  871.                 /*
  872.                  *  Following restrictions will be enforced only if the
  873.                  *  password is required i.e. UF_PASSWORD_NOTREQD flag
  874.                  *  is not set on this account.
  875.                 */
  876.                 if (u->flags & UF_PASSWD_CANT_CHANGE)
  877.                     return NERR_PasswordCantChange;
  878.                 if ( (current_time - u->last) < Ucb->hdr.min_passwd_age )
  879.                     return NERR_PasswordTooRecent;
  880.                 if (CheckPasswdHistory(new, u->old_passwds, UseEncryption))
  881.                     return NERR_PasswordHistConflict;
  882.                 if (passlen < Ucb->hdr.min_passwd_len)
  883.                     return NERR_PasswordTooShort;
  884.                 if ((nullpw) && (0 < Ucb->hdr.min_passwd_len))            /*@D07*/
  885.                     return NERR_PasswordTooShort;                         /*@D07*/
  886.             }
  887.             else        // password is not required
  888.                 {
  889.                 if (passlen != IGNORE_PASSWDLEN)
  890.                     {
  891.                     /*
  892.                      *  If password is not required on this account then
  893.                      *  the caller can either specify a null password ("")
  894.                      *  or supply one whichis not shorter than minimum
  895.                      *  password length modal. It is relevant only for
  896.                      *  LM2.0 clients.
  897.                     */
  898.                     if ( (passlen != 0) && (passlen < Ucb->hdr.min_passwd_len) )
  899.                         return NERR_PasswordTooShort;
  900.                 }
  901.             }   // LM1.X clients can bypass modal restrictions
  902.         }
  903.  
  904.         if (saverr)
  905.            {
  906.            /* We check other password restrictions and return those errors
  907.             * as appropriate before we return an error that the password
  908.             * sent was incorrect.  We also pause for INTRUDER_DELAY (3 seconds)
  909.             * before returning to slow down hackers trying to figure out a
  910.             * password.  We probably need to do an audit of this failure as
  911.             * well, but that's DCR material since it would mean defining a
  912.             * new audit entry.
  913.             */
  914.             DosSleep(INTRUDER_DELAY);
  915.             return saverr;
  916.         }
  917.  
  918.         SavePassword(u->old_passwds, u->passwd, Ucb->hdr.passwd_hist_len);
  919.         memcpyf(u->passwd, new, ENCRYPTED_PWLEN);
  920.         u->last = current_time;
  921.         LOCKDBFILE();
  922.         err = WriteUserObject(fd, pos, uo, TRUE);
  923.         UNLOCKDBFILE();
  924.         return err;
  925.  
  926. #else
  927.         return ERROR_NOT_SUPPORTED;
  928. #endif  /* REMONLY */
  929.  
  930.         /* quiet the compiler */
  931.         if (uname || old || new || passlen || fd || uo || pos || clevel);
  932. }
  933.  
  934. /*
  935.  *      UserGetInfo -- Get user's Information
  936.  *      Note That we will not return Password
  937.  *
  938.  *      Input:
  939.  *              uname - user name
  940.  *              level -- level of detail {0, 1, 2, 10, 11}
  941.  *              buf, buflen
  942.  *      Output:
  943.  *              total -- number of bytes available
  944.  *
  945.  *      Returns:
  946.  *              0 -- success
  947.  *              ERROR_INVALID_LEVEL
  948.  *              NERR_BufTooSmall
  949.  *              ERROR_MORE_DATA
  950.  *              NERR_UserNotFound
  951.  */
  952. int
  953. UserGetInfo(uname, level, buf, buflen, total)
  954. char far *uname;
  955. short level;
  956. char far *buf;
  957. unsigned short buflen;
  958. unsigned short far *total;
  959. {
  960. #ifndef REMONLY
  961.         int fd;
  962.         struct user_info_1 far *user;
  963.         struct user_info_2 far *user2;
  964.         struct user_info_10 far *user10;
  965.         struct user_info_11 far *user11;
  966.         struct user_object far *uo;
  967.         struct _userrec far *u;
  968.         SEL       sel;
  969.         unsigned short info_size;                                        /* @f08a */
  970.         int err = 0;
  971.         int sts;
  972.         char far *fixed_size_end;       /* end of fixed size data */     /* @f08a */
  973.         char far *end = buf+buflen;     /* end of buffer */
  974.         long pos;
  975.         char local_uname[UNLEN+1];
  976.  
  977.  
  978.         if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
  979.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  980.             return NERR_UserNotFound;
  981.  
  982.         /* open the named file */
  983.         if (err = OpenAccount(&fd))
  984.             return err;
  985.         if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
  986.             {
  987.             CloseAccount(fd);
  988.             return err;
  989.         }
  990.         else {
  991.                 uo = (struct user_object far *) PTR(sel, 0);
  992.                 u = &uo->uo_record;
  993.         }
  994.  
  995.         LOCKDBFILE();
  996.         sts = GetUserObject(fd, local_uname, uo, &pos);
  997.         CloseAccount(fd);
  998.         UNLOCKDBFILE();
  999.  
  1000.         if (sts)
  1001.                 {
  1002.                 DosFreeSeg(sel);
  1003.                 return sts;
  1004.         }
  1005.  
  1006.         if (level == LEVEL_0 ) {
  1007.                 *total = sizeof (struct user_info_0 );
  1008.                 if (buflen < sizeof(struct user_info_0) )
  1009.                         err = NERR_BufTooSmall;
  1010.                 else
  1011.                         strcpyf(buf, local_uname);
  1012.         }
  1013.         else if (level == LEVEL_1) {
  1014.                 *total = sizeof(struct user_info_1) +
  1015.                          strlenf( STRING(u, directory_o)) + 1 +
  1016.                          strlenf( STRING(u, comment_o)) + 1 +
  1017.                          strlenf( STRING(u, script_o)) + 1;
  1018.  
  1019.                 if (buflen < sizeof(struct user_info_1) )
  1020.                         err = NERR_BufTooSmall;
  1021.                 else {
  1022.                         user = (struct user_info_1 far *)buf;
  1023.                         strcpyf(user->usri1_name, local_uname);
  1024.                         strcpyf(user->usri1_password, Null_Passwd);
  1025.  
  1026.                  // @D06:begin: Put back d33038 fix.
  1027.                         if (u->last)                       // d33038
  1028.                           user->usri1_password_age = time_now() - u->last;
  1029.                         else                               // d33038
  1030.                           user->usri1_password_age = 0;    // d33038
  1031.                  // @D06:end
  1032.  
  1033.                         user->usri1_priv = u->user.uc0_priv;
  1034.  
  1035.                         user->usri1_home_dir = STRING (u, directory_o);
  1036.                         NetPackString(&user->usri1_home_dir,
  1037.                                 (char far *)(user+1), &end);
  1038.                         user->usri1_comment = STRING (u, comment_o);
  1039.                         NetPackString(&user->usri1_comment,
  1040.                                 (char far *)(user+1), &end);
  1041.                         user->usri1_flags = u->flags;
  1042.                         user->usri1_script_path = STRING (u, script_o);
  1043.                         NetPackString(&user->usri1_script_path,
  1044.                                 (char far *)(user+1), &end);
  1045.                 }
  1046.         }
  1047.         else if ((level == LEVEL_2) || (level == LEVEL_200)) {           /* @f08c */
  1048.                 if (level == LEVEL_2)                                    /* @f08a */
  1049.                 {                                                        /* @f08a */
  1050.                    info_size = sizeof(struct user_info_2);               /* @f08a */
  1051.                 }                                                        /* @f08a */
  1052.                 else                                                     /* @f08a */
  1053.                 {                                                        /* @f08a */
  1054.                    info_size = sizeof(struct user_info_200);             /* @f08a */
  1055.                 }                                                        /* @f08a */
  1056.                 *total = info_size  +                                    /* @f08c */
  1057.                          strlenf( STRING( u, directory_o)) +1     +
  1058.                          strlenf( STRING( u, comment_o))+1           +
  1059.                          strlenf( STRING( u, script_o))+1            +
  1060.                          strlenf( STRING( u, usr_comment_o))+1   +
  1061.                          strlenf( STRING( u, full_name_o))+1     +
  1062.                          strlenf( STRING( u, parms_o))+1             +
  1063.                          strlenf( STRING( u, workstation_o))+1   +
  1064.                          strlenf( STRING( u, logon_server_o))+1  +
  1065.                          UNITS_PER_WEEK/8;
  1066.  
  1067.  
  1068.                 if (buflen < info_size )                                 /* @f08c */
  1069.                         err = NERR_BufTooSmall;
  1070.                 else {
  1071.                         user2 = (struct user_info_2 far *)buf;
  1072.                         fixed_size_end = buf+info_size;                  /* @f08a */
  1073.                         strcpyf(user2->usri2_name, local_uname);
  1074.                         strcpyf(user2->usri2_password, Null_Passwd);
  1075.  
  1076.                  // @D06:begin: Put back d33038 fix.
  1077.                         if (u->last)                        // d33038
  1078.                           user2->usri2_password_age = time_now() - u->last;
  1079.                         else                                // d33038
  1080.                           user2->usri2_password_age = 0;    // d33038
  1081.                  // @D06:end
  1082.  
  1083.                         user2->usri2_priv = u->user.uc0_priv;
  1084.  
  1085.                         user2->usri2_home_dir = STRING(u, directory_o);
  1086.                         NetPackString(&user2->usri2_home_dir,
  1087.                                 fixed_size_end, &end);                   /* @f08c */
  1088.                         user2->usri2_comment = STRING (u, comment_o);
  1089.                         NetPackString(&user2->usri2_comment,
  1090.                                 fixed_size_end, &end);                   /* @f08c */
  1091.                         user2->usri2_flags = u->flags;
  1092.                         user2->usri2_script_path = STRING (u, script_o);
  1093.                         NetPackString(&user2->usri2_script_path,
  1094.                                 fixed_size_end, &end);                   /* @f08c */
  1095.                         user2->usri2_full_name = STRING (u, full_name_o);
  1096.                         NetPackString(&user2->usri2_full_name,
  1097.                                 fixed_size_end, &end);                   /* @f08c */
  1098.                         user2->usri2_usr_comment = STRING (u, usr_comment_o);
  1099.                         NetPackString(&user2->usri2_usr_comment,
  1100.                                 fixed_size_end, &end);                   /* @f08c */
  1101.                         user2->usri2_parms = STRING (u, parms_o);
  1102.                         NetPackString(&user2->usri2_parms,
  1103.                                 fixed_size_end, &end);                   /* @f08c */
  1104.                         /* workstations go here */
  1105.                         user2->usri2_workstations = STRING (u, workstation_o);
  1106.                         NetPackString(&user2->usri2_workstations,
  1107.                                 fixed_size_end, &end);                   /* @f08c */
  1108.                         user2->usri2_last_logon= u->last_logon;
  1109.                         user2->usri2_last_logoff = u->last_logoff;
  1110.                         user2->usri2_bad_pw_count = u->bad_pw_count;
  1111.                         user2->usri2_num_logons = u->num_logons;
  1112.                         user2->usri2_max_storage  = u->max_storage;
  1113.                         user2->usri2_acct_expires = u->acct_expires;
  1114.                         user2->usri2_logon_hours = u->logonhrs;
  1115.                         NetPackBitmap(&user2->usri2_logon_hours,
  1116.                                 fixed_size_end, &end, UNITS_PER_WEEK/8); /* @f08c */
  1117.                         /* logon server go here */
  1118.                         user2->usri2_logon_server = STRING (u, logon_server_o);
  1119.                         NetPackString(&user2->usri2_logon_server,
  1120.                                 fixed_size_end, &end);                   /* @f08c */
  1121.                         user2->usri2_country_code = u->country_code;
  1122.                         user2->usri2_code_page = u->code_page;
  1123.                         user2->usri2_auth_flags = u->user.uc0_auth_flags;
  1124.                         user2->usri2_units_per_week = UNITS_PER_WEEK;
  1125.  
  1126.                         /* level 200 asks that we return the user's */   /* @f08a */
  1127.                         /* serial number as well.                   */   /* @f08a */
  1128.                         if (level == LEVEL_200)                          /* @f08a */
  1129.                         {                                                /* @f08a */
  1130.                            ((struct user_info_200 far *)buf)->usri200_serial = /* @f08a */
  1131.                                u->user.uc0_guid.guid_serial;             /* @f08a */
  1132.                         }                                                /* @f08a */
  1133.                 }
  1134.         }
  1135.         else if (level == LEVEL_10) {
  1136.                 *total = sizeof(struct user_info_10) +
  1137.                          strlenf( STRING (u, comment_o))+1       +
  1138.                          strlenf( STRING (u, usr_comment_o))+1   +
  1139.                          strlenf( STRING (u, full_name_o))+1;
  1140.  
  1141.  
  1142.                 if (buflen < sizeof(struct user_info_10) )
  1143.                         err = NERR_BufTooSmall;
  1144.                 else {
  1145.                         user10 = (struct user_info_10 far *)buf;
  1146.                         strcpyf(user10->usri10_name, local_uname);
  1147.  
  1148.                         user10->usri10_comment = STRING (u, comment_o);
  1149.                         NetPackString(&user10->usri10_comment,
  1150.                                 (char far *)(user10+1), &end);
  1151.  
  1152.                         user10->usri10_usr_comment = STRING(u, usr_comment_o);
  1153.                         NetPackString(&user10->usri10_usr_comment,
  1154.                                 (char far *)(user10+1), &end);
  1155.  
  1156.                         user10->usri10_full_name = STRING(u, full_name_o);
  1157.                         NetPackString(&user10->usri10_full_name,
  1158.                                 (char far *)(user10+1), &end);
  1159.                 }
  1160.         }
  1161.         else if (level == LEVEL_11) {
  1162.                 *total = sizeof(struct user_info_11) +
  1163.                          strlenf( STRING (u, comment_o))+1      +
  1164.                          strlenf( STRING (u, usr_comment_o))+1  +
  1165.                          strlenf( STRING (u, full_name_o))+1    +
  1166.                          strlenf( STRING (u, directory_o))+1    +
  1167.                          strlenf( STRING (u, logon_server_o))+1 +
  1168.                          strlenf( STRING (u, workstation_o))+1  +
  1169.                          strlenf( STRING (u, parms_o))+1        +
  1170.                          UNITS_PER_WEEK/8;
  1171.  
  1172.  
  1173.                 if (buflen < sizeof(struct user_info_11) )
  1174.                         err = NERR_BufTooSmall;
  1175.                 else {
  1176.                         user11 = (struct user_info_11 far *)buf;
  1177.                         strcpyf(user11->usri11_name, local_uname);
  1178.  
  1179.                  // @D06:begin: Put back d33038 fix.
  1180.                         if (u->last)                           // d33038
  1181.                           user11->usri11_password_age = time_now() - u->last;
  1182.                         else                                   // d33038
  1183.                           user11->usri11_password_age = 0;     // d33038
  1184.                   // @D06:end
  1185.  
  1186.                         user11->usri11_priv = u->user.uc0_priv;
  1187.                         user11->usri11_auth_flags = u->user.uc0_auth_flags;
  1188.  
  1189.                         user11->usri11_comment = STRING (u, comment_o);
  1190.                         NetPackString(&user11->usri11_comment,
  1191.                                 (char far *)(user11+1), &end);
  1192.                         user11->usri11_usr_comment = STRING (u, usr_comment_o);
  1193.                         NetPackString(&user11->usri11_usr_comment,
  1194.                                 (char far *)(user11+1), &end);
  1195.                         user11->usri11_full_name = STRING (u, full_name_o);
  1196.                         NetPackString(&user11->usri11_full_name,
  1197.                                 (char far *)(user11+1), &end);
  1198.                         user11->usri11_home_dir = STRING (u, directory_o);
  1199.                         NetPackString(&user11->usri11_home_dir,
  1200.                                 (char far *)(user11+1), &end);
  1201.                         user11->usri11_parms = STRING (u, parms_o);
  1202.                         NetPackString(&user11->usri11_parms,
  1203.                                 (char far *)(user11+1), &end);
  1204.                         user11->usri11_last_logon= u->last_logon;
  1205.                         user11->usri11_last_logoff = u->last_logoff;
  1206.                         user11->usri11_bad_pw_count = u->bad_pw_count;
  1207.                         user11->usri11_num_logons = u->num_logons;
  1208.                         user11->usri11_country_code = u->country_code;
  1209.                         user11->usri11_code_page = u->code_page;
  1210.                         user11->usri11_max_storage = u->max_storage;
  1211.                         user11->usri11_units_per_week = UNITS_PER_WEEK;
  1212.                         /* logon server go here */
  1213.                         user11->usri11_logon_server =
  1214.                                 STRING (u, logon_server_o);
  1215.                         NetPackString(&user11->usri11_logon_server,
  1216.                                 (char far *)(user11+1), &end);
  1217.                         /* workstations go here */
  1218.                         user11->usri11_workstations = STRING(u, workstation_o);
  1219.                         NetPackString(&user11->usri11_workstations,
  1220.                                         (char far *)(user11+1), &end);
  1221.                         user11->usri11_logon_hours = u->logonhrs;
  1222.                         NetPackBitmap(&user11->usri11_logon_hours,
  1223.                                 (char far *)(user11+1), &end, UNITS_PER_WEEK/8);
  1224.                 }
  1225.         }
  1226.  
  1227.         DosFreeSeg(sel);
  1228.         if (!err && (*total > buflen))
  1229.                 return ERROR_MORE_DATA;
  1230.  
  1231.         return err;
  1232. #else
  1233.         return ERROR_NOT_SUPPORTED;
  1234. #endif  /* REMONLY */
  1235.  
  1236.         /* quiet the compiler */
  1237.         if (uname || level || buf || buflen || total);
  1238.  
  1239. }
  1240.  
  1241. /*
  1242.  *      UserSetInfo -- SetInformation
  1243.  *
  1244.  *      Password update restrictions are enforced if the password is
  1245.  *      not NULL_SETINFO_PASSWORD.
  1246.  *
  1247.  *      Input:
  1248.  *              uname - user name
  1249.  *              buf, buflen
  1250.  *              paramnum -- parameter number 0 (means whole structure)
  1251.  *              passlen     length of password (when it was plain text)
  1252.  *              last_admin  flag indicating if it is last admin account
  1253.  *
  1254.  *      Returns:
  1255.  *              0 -- success
  1256.  *              ERROR_INVALID_LEVEL
  1257.  *              NERR_BufTooSmall
  1258.  *              ERROR_MORE_DATA
  1259.  */
  1260. int
  1261. UserSetInfo( uname,  buf,  parmnum, rootdir, level, passlen, last_admin)
  1262. char far *uname;
  1263. char far *buf;
  1264. int parmnum;
  1265. char far *rootdir;
  1266. short level;
  1267. unsigned short passlen;
  1268. unsigned short last_admin;
  1269. {
  1270. #ifndef REMONLY
  1271.         int fd;
  1272.         struct user_info_1 far *user = (struct user_info_1 far *)buf;
  1273.         struct user_info_2 far *usr2 = (struct user_info_2 far *)buf;
  1274.         struct _userinfo far *u;
  1275.         struct user_object far *uo;
  1276.         SEL sel;
  1277.         USER far *user1;
  1278.         unsigned long type = 0;
  1279.         unsigned short full=TRUE;                                        /* @f08a */
  1280.         unsigned short old_priv;
  1281.         unsigned short new_priv;
  1282.         int err = 0;
  1283.         unsigned short flags;
  1284.         char    usr_passwd[ENCRYPTED_PWLEN];
  1285.         char far * home;
  1286.         char far * script;
  1287.         char far * rem;
  1288.         unsigned short  count;
  1289.         long pos;
  1290.         char local_uname[UNLEN+1];
  1291.  
  1292.  
  1293.         if (parmnum == U1_ALL && (err = ValidateUser(buf, level)) )
  1294.                 return err;
  1295.  
  1296.         if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
  1297.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  1298.             return NERR_UserNotFound;
  1299.  
  1300.         /* open the named file */
  1301.         if (err = OpenAccount(&fd))
  1302.             return err;
  1303.         if (err = DosAllocSeg(sizeof (struct _userinfo) + MAX_USER_SIZE, &sel, 0))
  1304.             {
  1305.             CloseAccount(fd);
  1306.             return err;
  1307.         }
  1308.         else {
  1309.                 uo = (struct user_object far *)PTR(sel, 0);
  1310.                 u = (struct _userinfo far *) PTR(sel, MAX_USER_SIZE);
  1311.         }
  1312.  
  1313.         LOCKDBFILE();
  1314.         if (err = GetUserObject (fd, local_uname, uo, &pos))
  1315.             {
  1316.             CloseAccount(fd);
  1317.             DosFreeSeg(sel);
  1318.             UNLOCKDBFILE();
  1319.             return err;
  1320.         }
  1321.         UserExpand (u, &uo->uo_record);
  1322.  
  1323.         /* we will allow setting fields on expired accounts */
  1324.  
  1325.         old_priv = u->user.uc0_priv;
  1326.  
  1327.         switch (parmnum)
  1328.             {
  1329.         case U1_ALL:
  1330.                 new_priv = ((struct user_info_1 far *)buf)->usri1_priv;
  1331.                 if ((old_priv == USER_PRIV_ADMIN) &&
  1332.                     (new_priv != USER_PRIV_ADMIN) && last_admin)
  1333.                     {
  1334.                     err = NERR_LastAdmin;
  1335.                     break;
  1336.                 }
  1337.  
  1338.                 u->user.uc0_priv = new_priv;
  1339.  
  1340.                 flags = ((struct user_info_1 far *)buf)->usri1_flags;
  1341.                 if ( !(flags & UF_SCRIPT) ||
  1342.                      ((flags & ~UF_SETTABLE_BITS) != 0) )
  1343.                     {
  1344.                     err = ERROR_INVALID_PARAMETER;
  1345.                     break;
  1346.                 }
  1347.                 if (!(u->flags & UF_ACCOUNTDISABLE) &&
  1348.                     (old_priv == USER_PRIV_ADMIN) &&
  1349.                     (flags & UF_ACCOUNTDISABLE) && last_admin)
  1350.                     {
  1351.                     err = NERR_LastAdmin;
  1352.                     break;
  1353.                 }
  1354.  
  1355.                 u->flags = flags;
  1356.  
  1357.                 /* guest accounts can't have operator rights */
  1358.                 if ( (user->usri1_priv == USER_PRIV_GUEST)  &&
  1359.                      (u->user.uc0_auth_flags) )
  1360.                     {
  1361.                     err = ERROR_INVALID_PARAMETER;
  1362.                     break;
  1363.                 }
  1364.  
  1365.  
  1366.                 if (level == LEVEL_1)
  1367.                         {
  1368.                         memcpyf(usr_passwd,
  1369.                                 ((struct user_info_1 far *)buf)->usri1_password,
  1370.                                 ENCRYPTED_PWLEN);
  1371.                         home = ((struct user_info_1 far *)buf)->usri1_home_dir;
  1372.                         rem = ((struct user_info_1 far *)buf)->usri1_comment;
  1373.                         script =
  1374.                             ((struct user_info_1 far *)buf)->usri1_script_path;
  1375.                 }
  1376.                 else if ((level == LEVEL_2) || (level == LEVEL_200))     /* @f08c */
  1377.                         {
  1378.                         memcpyf(usr_passwd,
  1379.                                 ((struct user_info_2 far *)buf)->usri2_password,
  1380.                                 ENCRYPTED_PWLEN);
  1381.                         home = ((struct user_info_2 far *)buf)->usri2_home_dir;
  1382.                         rem = ((struct user_info_2 far *)buf)->usri2_comment;
  1383.                         script =
  1384.                             ((struct user_info_2 far *)buf)->usri2_script_path;
  1385.                         /* explicitly level 2 stuff */
  1386.                         if (usr2->usri2_usr_comment != NULL)
  1387.                             strcpyf(u->usr_comment, usr2->usri2_usr_comment);
  1388.                         if (usr2->usri2_parms != NULL)
  1389.                                 strcpyf(u->parms, usr2->usri2_parms);
  1390.                         if (usr2->usri2_full_name != NULL)
  1391.                                 strcpyf(u->full_name, usr2->usri2_full_name);
  1392.                         u->acct_expires = usr2->usri2_acct_expires;
  1393.                         u->last_logon =  usr2->usri2_last_logon;   /* @d01a  */
  1394.                         u->last_logoff = usr2->usri2_last_logoff;  /* @d01a  */
  1395.                         u->max_storage = usr2->usri2_max_storage;
  1396.                         if (usr2->usri2_logon_hours != NULL)
  1397.                                 memcpyf(u->logonhrs, usr2->usri2_logon_hours,
  1398.                                                               UNITS_PER_WEEK/8);
  1399.                         /* workstation list handling Postponed */
  1400.                         if (usr2->usri2_workstations != NULL)
  1401.                             {
  1402.                             if (I_NetListCanonicalize(NULL,
  1403.                                                 usr2->usri2_workstations,
  1404.                                                 LIST_DELIMITER_STR_API,
  1405.                                                 u->workstation,
  1406.                                                 sizeof(u->workstation),
  1407.                                                 &count,
  1408.                                                 NULL,
  1409.                                                 0,
  1410.                                                 NAMETYPE_COMPUTER|
  1411.                                                 OUTLIST_TYPE_API|
  1412.                                                 INLC_FLAGS_CANONICALIZE) ||
  1413.                                                 (count > MAXWORKSTATIONS))
  1414.                                 {
  1415.                                 err = ERROR_INVALID_PARAMETER;
  1416.                                 break;
  1417.                             }
  1418.                         }
  1419.                         /* set logon server */
  1420.                         /* Note that logon_server == NULL will leave present
  1421.                          * value of this field unchanged. logon_server name is
  1422.                          * expected and is stored in the form \\logonserver
  1423.                         */
  1424.                         if (usr2->usri2_logon_server != NULL)
  1425.                           {
  1426.                           type = 0;
  1427.                           if (usr2->usri2_logon_server[0] == '\0')
  1428.                               u->logon_server[0] = '\0';
  1429.                           else if (I_NetPathCanonicalize( NULL,
  1430.                                                           usr2->usri2_logon_server,
  1431.                                                           u->logon_server,
  1432.                                                           UNCLEN+1,
  1433.                                                           NULL, &type, 0L) ||
  1434.                               ((type != ITYPE_UNC_WC) && (type != ITYPE_UNC_COMPNAME)))
  1435.                               {
  1436.                               err = ERROR_INVALID_PARAMETER;
  1437.                               break;
  1438.                           }
  1439.                         }
  1440.  
  1441.                         u->country_code = usr2->usri2_country_code;
  1442.                         u->code_page = usr2->usri2_code_page;
  1443.                         u->user.uc0_auth_flags = usr2->usri2_auth_flags;
  1444.  
  1445.                         /* set serial number to one provided if level == 200 */  /* @f08a */
  1446.                         /* and serial given is different than old one.       */  /* @f08a */
  1447.                         if ((level == LEVEL_200) &&                              /* @f08a */
  1448.                             (u->user.uc0_guid.guid_serial !=                     /* @f08a */
  1449.                              ((struct user_info_200 far *)buf)->usri200_serial)) /* @f08a */
  1450.                         {                                                        /* @f08a */
  1451.                            u->user.uc0_guid.guid_serial =                        /* @f08a */
  1452.                              ((struct user_info_200 far *)buf)->usri200_serial;  /* @f08a */
  1453.                            full = FULL_USE_SERIAL;                               /* @f08a */
  1454.                         }                                                        /* @f08a */
  1455.                 }
  1456.                 /*
  1457.                  * Following is common path for all levels
  1458.                  *
  1459.                  * Warning: Note that FLAGs have been just set to new value
  1460.                  *          We will use new values
  1461.                  *          allow zerolength password if notreqd bit Set
  1462.                  *          bypass password checks for LM1.0/1.1 clients
  1463.                 */
  1464.  
  1465.                  if (passlen != IGNORE_PASSWDLEN)       /* Not lm1.0 case */
  1466.                    {
  1467.                    if (u->flags & UF_PASSWD_NOTREQD)
  1468.                        {
  1469.                        if ((passlen != 0) && passlen < Ucb->hdr.min_passwd_len)
  1470.                            {
  1471.                            err = NERR_PasswordTooShort;
  1472.                            break;
  1473.                        }
  1474.                    }
  1475.                    else if (passlen < Ucb->hdr.min_passwd_len)
  1476.                        {
  1477.                        err = NERR_PasswordTooShort;
  1478.                        break;
  1479.                    }
  1480.                  } /* end lm1.0 case */
  1481.  
  1482.                 /*
  1483.                  * check password update restrictions and save the
  1484.                  * current password for history checking
  1485.                 */
  1486.                 if (err = UpdatePassword(u->user.uc0_guid.guid_uid, usr_passwd,
  1487.                                        u->passwd, u->old_passwds, &u->last))
  1488.                         break;
  1489.  
  1490.                 if (home != NULL) {       /*   @P01A  */
  1491.                    if (err = SetHomeDir(u->flags, home, u->directory, sizeof(u->directory)))
  1492.                        break;
  1493.                 }                         /*   @P01A  */
  1494.                 /*
  1495.                  * replace the old "super" group membership
  1496.                  * Unmark old membership first.
  1497.                 */
  1498.                 if (old_priv == USER_PRIV_ADMIN)
  1499.                         MARKOFF(u->user.uc0_groups, Ucb->AdminsId);
  1500.                 else if (old_priv == USER_PRIV_GUEST)
  1501.                         MARKOFF(u->user.uc0_groups, Ucb->GuestsId);
  1502.                 else if (old_priv == USER_PRIV_USER)
  1503.                         MARKOFF(u->user.uc0_groups, Ucb->UsersId);
  1504.  
  1505.                 if (u->user.uc0_priv == USER_PRIV_ADMIN)
  1506.                         MARKUSE(u->user.uc0_groups, Ucb->AdminsId);
  1507.                 else if (u->user.uc0_priv == USER_PRIV_GUEST)
  1508.                         MARKUSE(u->user.uc0_groups, Ucb->GuestsId);
  1509.                 else if (u->user.uc0_priv == USER_PRIV_USER)
  1510.                         MARKUSE(u->user.uc0_groups, Ucb->UsersId);
  1511.  
  1512.                 if (rem != NULL)
  1513.                         strcpyf(u->comment, rem);
  1514.  
  1515.                 if (script != NULL) {     /*   @P01A  */
  1516.                    err = SetScriptPath(script, u->script, sizeof(u->script));
  1517.                 }                         /*   @P01A  */
  1518.                 break;
  1519.  
  1520.         case U1_PASSWD:
  1521.              /*
  1522.               * Warning: PASSWD_CANT_CHG not checked since its admin only
  1523.               * Allow zerolength password if passwd_notreqd bit set
  1524.               * bypass passlen checks for lm1.0 clients
  1525.              */
  1526.              if (passlen != IGNORE_PASSWDLEN)
  1527.                 {
  1528.                 if (u->flags & UF_PASSWD_NOTREQD)
  1529.                     {
  1530.                     if ((passlen != 0) && passlen < Ucb->hdr.min_passwd_len)
  1531.                         {
  1532.                         err = NERR_PasswordTooShort;
  1533.                         break;
  1534.                     }
  1535.                 }
  1536.                 else if (passlen < Ucb->hdr.min_passwd_len)
  1537.                     {
  1538.                     err = NERR_PasswordTooShort;
  1539.                     break;
  1540.                 }
  1541.              } /* end lm1.0 case */
  1542.              err = UpdatePassword(u->user.uc0_guid.guid_uid, buf,
  1543.                                      u->passwd, u->old_passwds, &u->last);
  1544.                 break;
  1545.  
  1546.         case U1_PRIV:
  1547.                 /* can not change priv of last admin account */
  1548.                 new_priv = *(unsigned short far *)buf;
  1549.                 if ( (new_priv != USER_PRIV_USER) &&
  1550.                      (new_priv != USER_PRIV_ADMIN) &&
  1551.                      (new_priv != USER_PRIV_GUEST) )
  1552.                     {
  1553.                     err = ERROR_INVALID_PARAMETER;
  1554.                     break;
  1555.                 }
  1556.                 if ((old_priv == USER_PRIV_ADMIN) &&
  1557.                     (new_priv != USER_PRIV_ADMIN) && last_admin)
  1558.                     {
  1559.                     err = NERR_LastAdmin;
  1560.                     break;
  1561.                 }
  1562.                 if (new_priv > USER_PRIV_MAX)
  1563.                     err = ERROR_INVALID_PARAMETER;
  1564.                 else if (new_priv == USER_PRIV_GUEST && u->user.uc0_auth_flags)
  1565.                     err = ERROR_INVALID_PARAMETER;
  1566.                 else
  1567.                         {
  1568.                         u->user.uc0_priv = new_priv;
  1569.  
  1570.                         /* Unmark old membership */
  1571.                         if (old_priv == USER_PRIV_ADMIN)
  1572.                                 MARKOFF(u->user.uc0_groups, Ucb->AdminsId);
  1573.                         else if (old_priv == USER_PRIV_GUEST)
  1574.                                 MARKOFF(u->user.uc0_groups, Ucb->GuestsId);
  1575.                         else if (old_priv == USER_PRIV_USER)
  1576.                                 MARKOFF(u->user.uc0_groups, Ucb->UsersId);
  1577.  
  1578.                         /* mark new membership */
  1579.                         if (u->user.uc0_priv == USER_PRIV_ADMIN)
  1580.                                 MARKUSE(u->user.uc0_groups, Ucb->AdminsId);
  1581.                         else if (u->user.uc0_priv == USER_PRIV_GUEST)
  1582.                                 MARKUSE(u->user.uc0_groups, Ucb->GuestsId);
  1583.                         else if (u->user.uc0_priv == USER_PRIV_USER)
  1584.                                 MARKUSE(u->user.uc0_groups, Ucb->UsersId);
  1585.                 }
  1586.                 break;
  1587.  
  1588.         case U1_DIR:
  1589.  
  1590.                 err = SetHomeDir(u->flags, buf, u->directory, sizeof(u->directory));
  1591.                 break;
  1592.  
  1593.         case U1_COMMENT:
  1594.                 err = vcopy(u->comment, buf, sizeof(u->comment));
  1595.                 break;
  1596.  
  1597.         case U1_USER_FLAGS:
  1598.  
  1599.                 flags = *((unsigned short far *)buf);
  1600.                 if ( !(flags & UF_SCRIPT) ||
  1601.                      ((flags & ~UF_SETTABLE_BITS) != 0) )
  1602.                         err = ERROR_INVALID_PARAMETER;
  1603.                 else if (!(u->flags & UF_ACCOUNTDISABLE) &&
  1604.                          (old_priv == USER_PRIV_ADMIN) &&
  1605.                          (flags & UF_ACCOUNTDISABLE) && last_admin )
  1606.                         err = NERR_LastAdmin;
  1607.  
  1608.                 if (!err)
  1609.                         u->flags = flags;
  1610.                 break;
  1611.  
  1612.         case U1_SCRIPT_PATH:
  1613.  
  1614.                 err = SetScriptPath(buf, u->script, sizeof(u->script));
  1615.                 break;
  1616.  
  1617.         case PARMNUM_USR_COMMENT:
  1618.                 err = vcopy(u->usr_comment, buf, sizeof(u->usr_comment));
  1619.                 break;
  1620.  
  1621.         case PARMNUM_PARMS:
  1622.                 err = vcopy(u->parms, buf, sizeof(u->parms));
  1623.                 break;
  1624.  
  1625.         case PARMNUM_FULL_NAME:
  1626.                 /* should we also check the full name for valid characters */
  1627.                 err = vcopy(u->full_name, buf, sizeof(u->full_name));
  1628.                 break;
  1629.  
  1630.         case PARMNUM_WORKSTATIONS:
  1631.                 if (I_NetListCanonicalize(NULL,
  1632.                                           buf,
  1633.                                           LIST_DELIMITER_STR_API,
  1634.                                           u->workstation,
  1635.                                           sizeof(u->workstation),
  1636.                                           &count,
  1637.                                           NULL, 0,
  1638.                                           NAMETYPE_COMPUTER|OUTLIST_TYPE_API|
  1639.                                           INLC_FLAGS_CANONICALIZE) ||
  1640.                                           (count > MAXWORKSTATIONS))
  1641.                         err = ERROR_INVALID_PARAMETER;
  1642.                 break;
  1643.  
  1644.         case PARMNUM_ACCT_EXPIRES:
  1645.                 u->acct_expires = *(long far *)buf;
  1646.                 break;
  1647.  
  1648.         case PARMNUM_MAX_STORAGE:
  1649.                 u->max_storage = *(long far *)buf;
  1650.                 break;
  1651.  
  1652.         case PARMNUM_LOGON_HOURS:
  1653.                 memcpyf(u->logonhrs, buf, sizeof(u->logonhrs));
  1654.                 break;
  1655.  
  1656.         case PARMNUM_LOGON_SERVER:
  1657.                 type = 0;
  1658.                 if (buf[0] == '\0')
  1659.                     u->logon_server[0] = '\0';
  1660.                 else if (I_NetPathCanonicalize( NULL,
  1661.                                                 buf,
  1662.                                                 u->logon_server, UNCLEN+1,
  1663.                                                 NULL, &type, 0L) ||
  1664.                                                 ((type != ITYPE_UNC_WC) &&
  1665.                                                 (type != ITYPE_UNC_COMPNAME)))
  1666.                         err = ERROR_INVALID_PARAMETER;
  1667.                 break;
  1668.  
  1669.         case PARMNUM_COUNTRY_CODE:
  1670.                 u->country_code = *((unsigned short far *)buf);
  1671.                 break;
  1672.  
  1673.         case PARMNUM_AUTH_FLAGS:
  1674.                 if ((*((unsigned short far *)buf) & ~(AF_SETTABLE_BITS)) != 0)
  1675.                         err = ERROR_INVALID_PARAMETER;
  1676.                 else if (old_priv == USER_PRIV_GUEST)
  1677.                         err = ERROR_INVALID_PARAMETER;
  1678.                 else
  1679.                         u->user.uc0_auth_flags = *(unsigned long far *)buf;
  1680.                 break;
  1681.  
  1682.         case PARMNUM_LAST_LOGON:
  1683.                 u->last_logon = *(long far *)buf;
  1684.                 break;
  1685.  
  1686.         case PARMNUM_LAST_LOGOFF:
  1687.                 u->last_logoff = *(long far *)buf;
  1688.                 break;
  1689.  
  1690.         case PARMNUM_BADPW_COUNT:
  1691.                 u->bad_pw_count = *(unsigned short far *)buf;
  1692.                 break;
  1693.  
  1694.         case PARMNUM_NUM_LOGONS:
  1695.                 u->num_logons = *(unsigned short far *)buf;
  1696.                 break;
  1697.  
  1698.         case PARMNUM_CODE_PAGE:
  1699.                 u->code_page = *(unsigned short far *)buf;
  1700.                 break;
  1701.  
  1702.         case PARMNUM_PASSWD_EXPIRED:
  1703.               if ((int *)*buf)
  1704.                 u->last = 0L;
  1705.               else /* only reset the time if we marked it expired */
  1706.                 if (!u->last)
  1707.                    u->last = time_now();
  1708.             break;
  1709.         default:
  1710.                 err = ERROR_INVALID_PARAMETER;
  1711.         }
  1712.  
  1713.         if (! err)
  1714.                 {
  1715.                 UserCompress (&uo->uo_record, u);
  1716.                 if (err = WriteUserObject (fd, &pos, uo, full))          /* @f08c */
  1717.                         ;
  1718.                 else
  1719.                     {
  1720.                     LOCKUSEG();
  1721.                     if (user1 = FindUidInCache(u->user.uc0_guid.guid_uid,
  1722.                                         u->user.uc0_guid.guid_serial))
  1723.                         {
  1724.                         /* update account privs and operator rights */
  1725.                         user1->uc0_priv = u->user.uc0_priv;
  1726.                         user1->uc0_auth_flags = u->user.uc0_auth_flags;
  1727.                         /* copy new group bitmap */
  1728.                         memcpyf(user1->uc0_groups, u->user.uc0_groups, MAXGROUP/8);
  1729.  
  1730.                         /* LM20 server looks in UAS cache for priv info */
  1731.                         KickPinballSem();
  1732.                     }
  1733.                     UNLOCKUSEG();
  1734.                 }
  1735.         }
  1736.  
  1737.         UNLOCKDBFILE();
  1738.         DosFreeSeg(sel);
  1739.         CloseAccount(fd);
  1740.         return err;
  1741. #else
  1742.         return ERROR_NOT_SUPPORTED;
  1743. #endif  /* REMONLY */
  1744.  
  1745.         /* quiet the compiler */
  1746.        if (uname || buf || parmnum || rootdir || level || passlen || last_admin)
  1747.             ;
  1748. }
  1749.  
  1750. /*
  1751.  *      UserDel -- Delete a named user
  1752.  *
  1753.  *      Input:
  1754.  *              uname           username
  1755.  *              last_admin      if set implies that there is only 1 admin left
  1756.  *      Returns:
  1757.  *
  1758.  *              0 -- success
  1759.  *              NERR_UserNotFound
  1760.  *              NERR_ACFFileIOFail
  1761.  */
  1762. int
  1763. UserDel(uname, last_admin)
  1764. char far *uname;
  1765. unsigned short last_admin;
  1766. {
  1767. #ifndef REMONLY
  1768.         int fd;
  1769.         int err = 0;            /* assume no error */
  1770.         struct user_object far *uo;
  1771.         SEL             sel;
  1772.         unsigned short  eread;
  1773.         unsigned short  etotal;
  1774.         unsigned short  size;
  1775.         struct session_info_10 far * sessinfo;
  1776.         char   tmp[UNCLEN+1];
  1777.         long pos;
  1778.         struct user_cache_0 far *user;
  1779.         char local_uname[UNLEN+1];
  1780.  
  1781.         if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
  1782.                         sizeof(local_uname), NAMETYPE_USER, 0L))
  1783.             return NERR_UserNotFound;
  1784.  
  1785.         if (err = OpenAccount(&fd))
  1786.             return err;
  1787.         if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
  1788.             {
  1789.             CloseAccount(fd);
  1790.             return err;
  1791.         }
  1792.         else
  1793.                 uo = (struct user_object far *) PTR(sel, 0);
  1794.  
  1795.         LOCKDBFILE();
  1796.  
  1797.         if (err = GetUserObject (fd, local_uname, uo, &pos))
  1798.             ;            /*  name not found */
  1799.  
  1800.         else if (((uo->uo_record.user.uc0_priv & USER_PRIV_MASK) == USER_PRIV_ADMIN) && !(uo->uo_record.flags & UF_ACCOUNTDISABLE) && last_admin)
  1801.                 err = NERR_LastAdmin;
  1802.  
  1803.         else if (AccessRemoveId(uo->uo_record.user.uc0_guid.guid_uid,
  1804.                                 uo->uo_record.user.uc0_guid.guid_serial))
  1805.                 err =  NERR_ACFFileIOFail;
  1806.         else {
  1807.                 /* purge this users record from the cache */
  1808.                 if (DeleteUserObject(fd, pos, uo) !=  0)
  1809.                         err = NERR_ACFFileIOFail;
  1810.                 else  {
  1811.                         LOCKUSEG();
  1812.                         if (user = FindUidInCache(
  1813.                                 uo->uo_record.user.uc0_guid.guid_uid,
  1814.                                 uo->uo_record.user.uc0_guid.guid_serial))
  1815.                         {
  1816.                                 PurgeUserRecord(user);
  1817.                         }
  1818.  
  1819.                         Ucb->usercnt --;                /* Update counter */
  1820.                         KickPinballSem();
  1821.                         UNLOCKUSEG();
  1822.                 }
  1823.         }
  1824.         if (fd >=0 )
  1825.                 CloseAccount(fd);
  1826.         DosFreeSeg(sel);
  1827.         UNLOCKDBFILE();
  1828.  
  1829.         if (err)
  1830.             return err;
  1831.  
  1832.         /* Tell any netlogon service that is around about this user
  1833.          * being deleted so that the logon tables can be updated.  This
  1834.          * function lives in api\ssi\ssiutil.c.  It's a side affect
  1835.          * so we don't care about errors.
  1836.          */
  1837.  
  1838.         FreeUserEntries(local_uname);
  1839.  
  1840.         /* quit if server is not running */
  1841.         if (GetServerSegs())
  1842.             return NERR_Success;
  1843.         else
  1844.             FreeServerSegs();
  1845.  
  1846.         /*
  1847.          * All sessions belonging to this user are deleted.
  1848.          * Note that we map evry error to InternalError since we
  1849.          * have already deleted the user's record in the database and
  1850.          * removed him from the cache.
  1851.          *
  1852.          * Warning: if you try to delete your own account on a remote
  1853.          *          server, provided you have privs to do that, your
  1854.          *          session will be deleted and most likely you will
  1855.          *          get VC_DISCONNECTED error from redir since the
  1856.          *          transaction never got completed.
  1857.         */
  1858.         err = NetSessionEnum(NULL, 10, NULL, 0, &eread, &etotal);
  1859.         if (err == NERR_BufTooSmall || err == ERROR_MORE_DATA || err == 0)
  1860.             {
  1861.             if (etotal == 0)
  1862.                 return NERR_Success;
  1863.             /* get the worst case size estimate */
  1864.             size = sizeof(struct session_info_10) + (UNLEN+1) + (CNLEN+1);
  1865.                 size *= etotal;
  1866.             if (err = DosAllocSeg(size, &sel, 0))
  1867.                 return NERR_InternalError;
  1868.             else
  1869.                 sessinfo = (struct session_info_10 far *) PTR(sel, 0);
  1870.         }
  1871.         if (NetSessionEnum(NULL, 10, (char far *) sessinfo, size, &eread, &etotal))
  1872.             {
  1873.             DosFreeSeg(sel);
  1874.             return NERR_InternalError;
  1875.         }
  1876.         /* walk through the buffer looking for name of this user */
  1877.         while (etotal --)
  1878.             {
  1879.             if (!I_NetNameCompare(NULL, local_uname, sessinfo->sesi10_username,
  1880.                  NAMETYPE_USER, 0L))
  1881.                 {
  1882.                 strcpyf(tmp, "\\\\");
  1883.                 strcatf(tmp, sessinfo->sesi10_cname);
  1884.                 if (WSessionDel(NULL, tmp, 0, NULL, ACCESS_LOCAL))
  1885.                     break;
  1886.             }
  1887.             sessinfo++;
  1888.         }
  1889.  
  1890.         DosFreeSeg(sel);
  1891.         return err;
  1892. #else
  1893.         return ERROR_NOT_SUPPORTED;
  1894. #endif  /* REMONLY */
  1895.  
  1896.         /* quiet the compiler */
  1897.         if (uname || last_admin);
  1898. }
  1899.  
  1900.  
  1901. /*
  1902.  * Vcopy -- Verify the length and copy
  1903.  */
  1904. static int near
  1905. vcopy(to, from, size)
  1906. char far *to;
  1907. char far *from;
  1908. int size;
  1909. {
  1910.         int len;
  1911.  
  1912.         if ((len = strlenf(from) ) >= size)
  1913.                 return ERROR_INVALID_PARAMETER;
  1914.         memcpyf(to, from, len+1);
  1915.         return 0;
  1916. }
  1917.  
  1918.  
  1919. /****   UserGetModals
  1920.  *
  1921.  *      Purpose:    Get global User Modals
  1922.  *
  1923.  *      Entry:      level       level of details requested (MBZ for LM1.2)
  1924.  *                  buf         buffer to return data in
  1925.  *                  buflen      size of buffer must be at least sizeof struct
  1926.  *                  total       total bytes available
  1927.  *
  1928.  *      Exit:       buffer filled with struct user_modals_info_0
  1929.  *
  1930.  *      Return:     NERR_Success or OS/2 error as appropriate
  1931.  *
  1932.  *      NOTE:       This function will succeed even though UAS may not be
  1933.  *                  running but a good access database (net.acc) exists.
  1934.  *
  1935. */
  1936. int
  1937. UserGetModals(level, buf, buflen, total)
  1938. short level;
  1939. char far * buf;
  1940. unsigned short buflen;
  1941. unsigned short far * total;
  1942. {
  1943. #ifndef REMONLY
  1944.         int     fd = 0;  // Jay Fix for SA
  1945.         int     errfd = 0 ;  // Jay Fix for SA
  1946.         int     err = 0;
  1947.         long    pos;
  1948.         unsigned short bytesread;
  1949.         char far * end;
  1950.         char    hdrbuf[sizeof(struct _ahdr)];
  1951.         struct  user_modals_info_0 far *m;
  1952.         struct  user_modals_info_1 far *p;
  1953.         struct  user_modals_info_101 far *p1;
  1954.         struct  _ahdr far *h;
  1955.  
  1956.         end = buf + buflen;
  1957.  
  1958.         if (Ucb == NULL)
  1959.             errfd = OpenAccountSpecial(&fd);
  1960.         else
  1961.             errfd = OpenAccount(&fd);
  1962.  
  1963.         if (errfd == NERR_Success)
  1964.             {
  1965.  
  1966.             if (Ucb != NULL)
  1967.                LOCKDBFILE();
  1968.  
  1969.             if ((err = DosChgFilePtr(fd, 0L, 0, &pos)))
  1970.                 ;
  1971.             else if ((err = DosRead(fd, hdrbuf, sizeof(struct _ahdr),
  1972.                              &bytesread)) || bytesread != sizeof(struct _ahdr))
  1973.                 err = err ? err : NERR_ACFFileIOFail;
  1974.             else
  1975.                 h = (struct _ahdr far *) hdrbuf;
  1976.  
  1977.             if (Ucb != NULL)
  1978.                 UNLOCKDBFILE();
  1979.  
  1980.         }
  1981.  
  1982.         else                              // Jay Fix for SA
  1983.                 return errfd;             // Jay Fix for SA
  1984.  
  1985.         if (err)
  1986.         {
  1987.             CloseAccount(fd);
  1988.             return err;
  1989.         }
  1990.  
  1991.         if (level == LEVEL_0)
  1992.                 {
  1993.                 m = (struct user_modals_info_0 far *)buf;
  1994.                 *total = sizeof(struct user_modals_info_0);
  1995.                 if (buflen < sizeof(struct user_modals_info_0))
  1996.                     {
  1997.                     CloseAccount(fd);
  1998.                     return NERR_BufTooSmall;
  1999.                 }
  2000.                 m->usrmod0_min_passwd_len = h->min_passwd_len;
  2001.                 m->usrmod0_max_passwd_age = h->max_passwd_age;
  2002.                 m->usrmod0_min_passwd_age = h->min_passwd_age;
  2003.                 m->usrmod0_force_logoff   = h->force_logoff;
  2004.                 m->usrmod0_password_hist_len = h->passwd_hist_len;
  2005.                 m->usrmod0_maxbadpw = h->max_bad_passwd;
  2006.         }
  2007.         else if (level == LEVEL_1)
  2008.                 {
  2009.                 *total = sizeof(struct user_modals_info_1) +
  2010.                          strlenf(h->primary.uas0_computer) + 1;
  2011.                 if (buflen < sizeof(struct user_modals_info_1))
  2012.                     {
  2013.                     CloseAccount(fd);
  2014.                     return NERR_BufTooSmall;
  2015.                 }
  2016.                 p = (struct user_modals_info_1 far *)buf;
  2017.                 p->usrmod1_role = h->role;
  2018.                 p->usrmod1_primary = h->primary.uas0_computer;
  2019.                 NetPackString(&p->usrmod1_primary, (char far *)(p+1), &end);
  2020.                 if (*total > buflen)
  2021.                     err = ERROR_MORE_DATA;
  2022.         }
  2023.         else if (level == LEVEL_100)
  2024.                 {
  2025.                 *total = sizeof(struct user_modals_info_100);
  2026.                 if (buflen < sizeof(struct user_modals_info_100))
  2027.                     {
  2028.                     CloseAccount(fd);
  2029.                     return NERR_BufTooSmall;
  2030.                 }
  2031.                 memcpyf(((struct user_modals_info_100 far *)buf)->usrmod100_DBIdInfo,
  2032.                                  h->DBIdInfo, DBIDINFO_SIZE);
  2033.         }
  2034.         else if (level == LEVEL_101)
  2035.                 {
  2036.                 *total = sizeof(struct user_modals_info_101) +
  2037.                          strlenf(h->local.uas0_computer) + 1 +
  2038.                          strlenf(h->primary.uas0_computer) + 1;
  2039.                 if (buflen < sizeof(struct user_modals_info_101))
  2040.                     {
  2041.                     CloseAccount(fd);
  2042.                     return NERR_BufTooSmall;
  2043.                 }
  2044.                 p1 = (struct user_modals_info_101 far *)buf;
  2045.                 p1->usrmod101_local_date = h->local.uas0_time_created;
  2046.                 p1->usrmod101_local_counter = h->local.uas0_serial_number;
  2047.                 p1->usrmod101_primary_date = h->primary.uas0_time_created;
  2048.                 p1->usrmod101_primary_counter = h->primary.uas0_serial_number;
  2049.                 p1->usrmod101_local_computer = h->local.uas0_computer;
  2050.                 NetPackString(&p1->usrmod101_local_computer,
  2051.                                              (char far *)(p1+1), &end);
  2052.                 p1->usrmod101_primary_computer = h->primary.uas0_computer;
  2053.                 NetPackString(&p1->usrmod101_primary_computer,
  2054.                                              (char far *)(p1+1), &end);
  2055.                 if (*total > buflen)
  2056.                     err = ERROR_MORE_DATA;
  2057.         }
  2058.  
  2059.         CloseAccount(fd);
  2060.         return err;
  2061. #else
  2062.         return ERROR_NOT_SUPPORTED;
  2063. #endif  /* REMONLY */
  2064.  
  2065.         /* quiet the compiler */
  2066.         if (level || buf || buflen || total);
  2067. }
  2068.  
  2069.  
  2070. /****   UserSetModals
  2071.  *
  2072.  *      Purpose:    Set global User Modals
  2073.  *
  2074.  *      Entry:      level       level of details requested (MBZ for LM1.2)
  2075.  *                  buf         filled with struct user_modals_info_0
  2076.  *                  buflen      size of buffer
  2077.  *                  parmnum     ordinal number of parameter to set
  2078.  *
  2079.  *      Exit:       appropriate fields in net.acc and cache (conditional)
  2080.  *                  modified
  2081.  *
  2082.  *      Return:     NERR_Success or OS/2 error as appropriate
  2083.  *
  2084.  *      NOTE:       This function will succeed at level 0 even though UAS may
  2085.  *                  not be running but a good access database (net.acc) exists.
  2086.  *
  2087. */
  2088. int
  2089. UserSetModals(level, buf, buflen, parmnum)
  2090. short level;
  2091. char far * buf;
  2092. unsigned short buflen;
  2093. short parmnum;
  2094. {
  2095. #ifndef REMONLY
  2096.         int     err, fd;
  2097.         long    new;
  2098.         unsigned short written;
  2099.         unsigned short bytesread;
  2100.         unsigned short role;
  2101.         struct  user_modals_info_0 far *m;
  2102.         char far * primary;
  2103.         struct  _ahdr far *p;
  2104.         char    hdrbuf[sizeof(struct _ahdr)];
  2105.         char    tmpbuf[CNLEN+1];
  2106.  
  2107.         if (Ucb == NULL)
  2108.             err = OpenAccountSpecial(&fd);
  2109.         else
  2110.             err = OpenAccount(&fd);
  2111.  
  2112.         if (err == NERR_Success)
  2113.             {
  2114.  
  2115.             if (Ucb != NULL)
  2116.                  LOCKDBFILE();
  2117.  
  2118.             if ((err = DosChgFilePtr(fd, 0L, 0, &new)))
  2119.                 ;
  2120.             else if ((err = DosRead(fd, hdrbuf, sizeof(struct _ahdr),
  2121.                              &bytesread)) || bytesread != sizeof(struct _ahdr))
  2122.                 err = err ? err : NERR_ACFFileIOFail;
  2123.             else
  2124.                 p = (struct _ahdr far *) hdrbuf;
  2125.  
  2126.             if (Ucb != NULL)
  2127.                  UNLOCKDBFILE();
  2128.         }
  2129.         if (err)
  2130.             {
  2131.             CloseAccount(fd);
  2132.             return err;
  2133.         }
  2134.  
  2135.         if (Ucb != NULL)
  2136.             LOCKDBFILE();
  2137.         if (level == LEVEL_0)
  2138.             {
  2139.             switch(parmnum)
  2140.                 {
  2141.                 case MODAL0_PARMNUM_ALL:
  2142.                     m = (struct user_modals_info_0 far *)buf;
  2143. //                  if (m->usrmod0_min_passwd_len < 0 ||
  2144.                     if (m->usrmod0_min_passwd_len > PWLEN)
  2145.                         {
  2146.                         err = ERROR_INVALID_PARAMETER;
  2147.                         break;
  2148.                     }
  2149.                     else
  2150.                         p->min_passwd_len = m->usrmod0_min_passwd_len;
  2151.                     if ((m->usrmod0_max_passwd_age < ONE_DAY) ||
  2152.                         (m->usrmod0_max_passwd_age < m->usrmod0_min_passwd_age))
  2153.                         {
  2154.                         err = ERROR_INVALID_PARAMETER;
  2155.                         break;
  2156.                     }
  2157.                     p->max_bad_passwd = m->usrmod0_maxbadpw;
  2158.                     p->max_passwd_age = m->usrmod0_max_passwd_age;
  2159.                     p->min_passwd_age = m->usrmod0_min_passwd_age;
  2160.                     p->force_logoff = m->usrmod0_force_logoff;
  2161. //                  if (m->usrmod0_password_hist_len < 0 ||
  2162.                     if (m->usrmod0_password_hist_len > DEF_MAX_PWHIST)
  2163.                         err = ERROR_INVALID_PARAMETER;
  2164.                     else
  2165.                         p->passwd_hist_len = m->usrmod0_password_hist_len;
  2166.                     break;
  2167.                 case MODAL0_PARMNUM_MIN_LEN:
  2168. //                  if (*(unsigned short far *)buf < 0 ||
  2169.                     if (*(unsigned short far *)buf > PWLEN)
  2170.                         err = ERROR_INVALID_PARAMETER;
  2171.                     else
  2172.                         p->min_passwd_len = *(unsigned short far *)buf;
  2173.                     break;
  2174.                 case MODAL0_PARMNUM_MAX_AGE:
  2175.                     if ((p->min_passwd_age > *(unsigned long far *)buf) ||
  2176.                         (*(unsigned long far *)buf < ONE_DAY))
  2177.                         err = ERROR_INVALID_PARAMETER;
  2178.                     else
  2179.                         p->max_passwd_age = *(unsigned long far *)buf;
  2180.                     break;
  2181.                 case MODAL0_PARMNUM_MIN_AGE:
  2182.                     if (p->max_passwd_age < *(unsigned long far *)buf)
  2183.                         err = ERROR_INVALID_PARAMETER;
  2184.                     else
  2185.                         p->min_passwd_age = *(unsigned long far *)buf;
  2186.                     break;
  2187.                 case MODAL0_PARMNUM_FORCEOFF:
  2188.                     p->force_logoff = *(unsigned long far *)buf;
  2189.                     break;
  2190.                 case MODAL0_PARMNUM_HISTLEN:
  2191. //                  if (*(unsigned short far *)buf < 0 ||
  2192.                     if (*(unsigned short far *)buf > DEF_MAX_PWHIST)
  2193.                         err = ERROR_INVALID_PARAMETER;
  2194.                     else
  2195.                         p->passwd_hist_len = *(unsigned short far *)buf;
  2196.                     break;
  2197.                 case MODAL0_PARMNUM_MAX_BADPW:
  2198.                     p->max_bad_passwd = *(unsigned short far *)buf;
  2199.                     break;
  2200.                 default:
  2201.                     err = ERROR_INVALID_PARAMETER;
  2202.             }
  2203.         }
  2204.         else if (level == LEVEL_1)
  2205.             {
  2206.             if (parmnum == MODAL1_PARMNUM_ALL)
  2207.                 {
  2208.                 primary = ((struct user_modals_info_1 far *)buf)->usrmod1_primary;
  2209.                 role = ((struct user_modals_info_1 far *)buf)->usrmod1_role;
  2210.             }
  2211.             else if (parmnum == MODAL1_PARMNUM_PRIMARY)
  2212.                 primary = buf;
  2213.             else if (parmnum == MODAL1_PARMNUM_ROLE)
  2214.                 role = *(unsigned short far *)buf;
  2215.  
  2216.             if (parmnum == MODAL1_PARMNUM_ALL || parmnum == MODAL1_PARMNUM_ROLE)
  2217.                 {
  2218.                 if ((role != UAS_ROLE_PRIMARY) &&
  2219.                     (role != UAS_ROLE_MEMBER)  &&
  2220.                     (role != UAS_ROLE_BACKUP)  &&
  2221.                     (role != UAS_ROLE_STANDALONE))
  2222.                     err = ERROR_INVALID_PARAMETER;
  2223.                 else
  2224.                     p->role = role;
  2225.             }
  2226.             if (parmnum == MODAL1_PARMNUM_ALL || parmnum == MODAL1_PARMNUM_PRIMARY)
  2227.                 {
  2228.                 if (primary == NULL)
  2229.                     ;
  2230.                 else if (primary[0] == '\0')
  2231.                     p->primary.uas0_computer[0] = '\0';
  2232.                 else
  2233.                     {
  2234.                     if (I_NetNameCanonicalize(NULL,
  2235.                                               primary,
  2236.                                               tmpbuf,   /* output buffer */
  2237.                                               CNLEN+1,  /* sizeof output buf */
  2238.                                               NAMETYPE_COMPUTER,
  2239.                                               0L))
  2240.                         err = ERROR_INVALID_PARAMETER;
  2241.                     else
  2242.                         strcpyf(p->primary.uas0_computer, tmpbuf);
  2243.                 }
  2244.             }
  2245.         }
  2246.         else if (level == LEVEL_100)
  2247.             {
  2248.             memcpyf(p->DBIdInfo,
  2249.                      ((struct user_modals_info_100 far *)buf)->usrmod100_DBIdInfo,
  2250.                      DBIDINFO_SIZE);
  2251.         }
  2252.         else if (level == LEVEL_101)
  2253.             {
  2254.             /* WARNING: special case for internal use, see uasuser.c */
  2255.             p->local.uas0_time_created =
  2256.                ((struct user_modals_info_101 far *)buf)->usrmod101_local_date;
  2257.             p->local.uas0_serial_number =
  2258.                ((struct user_modals_info_101 far *)buf)->usrmod101_local_counter;
  2259.             p->primary.uas0_time_created =
  2260.                ((struct user_modals_info_101 far *)buf)->usrmod101_primary_date;
  2261.             p->primary.uas0_serial_number =
  2262.                ((struct user_modals_info_101 far *)buf)->usrmod101_primary_counter;
  2263.  
  2264.             /* NULL primary name means the caller does not want to
  2265.              * change the primary. It is the responsibility of the
  2266.              * caller to make that decision.
  2267.              */
  2268.              if ( ( ((struct user_modals_info_101 far *)buf)->usrmod101_primary_computer) != NULL) /*d9983*/
  2269.                 strcpyf(p->primary.uas0_computer,                                                  /*d9983*/
  2270.                ((struct user_modals_info_101 far *)buf)->usrmod101_primary_computer );             /*d9983*/
  2271.         }
  2272.  
  2273.         /* Update disk record: update cache if disk update OK */
  2274.         if (err == NERR_Success)
  2275.             {
  2276.             if (!(err = DosChgFilePtr(fd, 0L, 0, &new)))
  2277.                 err = DosWrite(fd, (char far *) hdrbuf, sizeof(struct _ahdr), &written);
  2278.  
  2279.             if (err || (written != sizeof(struct _ahdr)))
  2280.                 err = err ? err : NERR_ACFFileIOFail;
  2281.         }
  2282.  
  2283.         if (Ucb != NULL && err == NERR_Success)
  2284.             {
  2285.             /* copy the new information in cache if UAS running */
  2286.             LOCKUSEG();
  2287.             if (level == LEVEL_0)
  2288.                 {
  2289.                 switch(parmnum)
  2290.                     {
  2291.                     case MODAL0_PARMNUM_ALL:
  2292.                         memcpyf((char far *) &Ucb->hdr, (char far *)p, sizeof(struct _ahdr));
  2293.                         break;
  2294.                     case MODAL0_PARMNUM_MIN_LEN:
  2295.                         Ucb->hdr.min_passwd_len = p->min_passwd_len;
  2296.                         break;
  2297.                     case MODAL0_PARMNUM_MAX_AGE:
  2298.                         Ucb->hdr.max_passwd_age = p->max_passwd_age;
  2299.                         break;
  2300.                     case MODAL0_PARMNUM_MIN_AGE:
  2301.                         Ucb->hdr.min_passwd_age = p->min_passwd_age;
  2302.                         break;
  2303.                     case MODAL0_PARMNUM_FORCEOFF:
  2304.                         Ucb->hdr.force_logoff = p->force_logoff;
  2305.                         break;
  2306.                     case MODAL0_PARMNUM_HISTLEN:
  2307.                         Ucb->hdr.passwd_hist_len = p->passwd_hist_len;
  2308.                         break;
  2309.                     case MODAL0_PARMNUM_MAX_BADPW:
  2310.                         Ucb->hdr.max_bad_passwd = p->max_bad_passwd;
  2311.                         break;
  2312.                 }
  2313.             }
  2314.             else if (level == LEVEL_1)
  2315.                 {
  2316.                 Ucb->hdr.role = p->role;
  2317.                 strcpyf(Ucb->hdr.primary.uas0_computer, p->primary.uas0_computer);
  2318.                 if (Ucb->hdr.role == UAS_ROLE_PRIMARY || Ucb->hdr.role == UAS_ROLE_STANDALONE)
  2319.                     Ucb->UpdatesOK = TRUE;
  2320.                 else
  2321.                     Ucb->UpdatesOK = FALSE;
  2322.             }
  2323.             else if (level == LEVEL_100)
  2324.                 memcpyf(Ucb->hdr.DBIdInfo, p->DBIdInfo, DBIDINFO_SIZE);
  2325.             else if (level == LEVEL_101)
  2326.                 {
  2327.                 /* WARNING: special case for internal use, see uasuser.c */
  2328.                 Ucb->hdr.local.uas0_time_created = p->local.uas0_time_created;
  2329.                 Ucb->hdr.local.uas0_serial_number = p->local.uas0_serial_number;
  2330.                 Ucb->hdr.primary.uas0_time_created = p->primary.uas0_time_created;
  2331.                 Ucb->hdr.primary.uas0_serial_number = p->primary.uas0_serial_number;
  2332.             }
  2333.  
  2334.             UNLOCKUSEG();
  2335.         }
  2336.  
  2337.         CloseAccount(fd);
  2338.         if (Ucb != NULL)
  2339.             UNLOCKDBFILE();
  2340.         return err;
  2341. #else
  2342.         return ERROR_NOT_SUPPORTED;
  2343. #endif  /* REMONLY */
  2344.  
  2345.         /* quiet the compiler */
  2346.         if (level || buf || buflen || parmnum)
  2347.             ;
  2348. }
  2349.  
  2350.  
  2351. #ifdef LOCKOUT
  2352. /*
  2353.  *  TrackBadPasswords
  2354.  *                  The purpose of this function is to bump the bad_pw_count
  2355.  *                  field in user's record and disable his account (lock out)
  2356.  *                  if bad password attempts have exceeded beyond the limit
  2357.  *                  specified by reserved1 modal. If the password matched
  2358.  *                  correctly and account was still enabled i.e. not locked
  2359.  *                  out, bad password count will be reset to 0. Bad password
  2360.  *                  tries are counted even though the account may have been
  2361.  *                  locked out. Note that last Admin account will never be
  2362.  *                  locked out.
  2363.  *
  2364.  *  Entry:
  2365.  *          u       struct _userrec far *
  2366.  *          fd      file handle of UAS database
  2367.  *
  2368.  *  Exit:
  2369.  *
  2370.  *
  2371. */
  2372. void
  2373. TrackBadPasswords(passwd_match, fd, u, wkstn)
  2374. int passwd_match;
  2375. int fd;
  2376. struct _userrec far *u;
  2377. char far * wkstn;
  2378. {
  2379.         unsigned short  err = 0;
  2380.         unsigned short  dummy;
  2381.         unsigned short  total;
  2382.         unsigned short  last_admin = FALSE;
  2383.  
  2384.         if (passwd_match)
  2385.             {
  2386.             if (u->flags & UF_ACCOUNTDISABLE)
  2387.                 return;
  2388.             else
  2389.                 u->bad_pw_count = 0;
  2390.         }
  2391.         else
  2392.             {
  2393.             (u->bad_pw_count)++;
  2394.             /* disable the account if we exceed reserved1 and it's active*/
  2395.             if (!(u->flags & UF_ACCOUNTDISABLE))
  2396.                 {
  2397.                 if (u->bad_pw_count > Ucb->hdr.reserved1)
  2398.                     {
  2399.                     /* do not disable the last Admin account */
  2400.                     if ((u->user.uc0_priv & USER_PRIV_MASK) == USER_PRIV_ADMIN)
  2401.                         {
  2402.                         if (!IsLastActiveUser(u->name, ADMINGROUP, &total))
  2403.                             u->flags |= UF_ACCOUNTDISABLE;
  2404.                     }
  2405.                 }
  2406.             }
  2407.         }
  2408.         /* update the bad_pw_count field reset or bump as the case maybe */
  2409.         WriteUserRec(fd, &u->user, TRUE);
  2410.         audit_alert_lockout(last_admin, u->name, wkstn);
  2411. }
  2412. #endif /* LOCKOUT */
  2413.  
  2414.  
  2415.  
  2416.  
  2417. /*
  2418.  *      SetHomeDir
  2419.  *
  2420.  *      Purpose:    Set the user's home directory field in the user
  2421.  *                  record if all the neccessary requirement are met.
  2422.  *
  2423.  *
  2424.  *      Notes:
  2425.  *                  If the user's account has UF_HOMEDIR_REQD flag set
  2426.  *                  then a valid absolute path (local or unc) must be
  2427.  *                  supplied for the home directory field. A null string
  2428.  *                  is not a valid path. In case of NetUserSetInfo with
  2429.  *                  zero parmnum the newly supplied flags are used for
  2430.  *                  verifying the restrictions whereas in case of non zero
  2431.  *                  parmnum the flgas stored in user's account are used.
  2432.  *
  2433.  *      Assumptions:
  2434.  *                  input arguments are presumed to be valid
  2435.  *
  2436. */
  2437. unsigned short
  2438. SetHomeDir(user_flags, in_homedir, out_homedir, outlen)
  2439. unsigned short  user_flags;
  2440. char far *  in_homedir;
  2441. char far *  out_homedir;
  2442. unsigned short  outlen;
  2443. {
  2444.         unsigned long   type = 0;
  2445.         unsigned short  is_homedir_null = FALSE;
  2446.  
  2447.  
  2448.         /*
  2449.          * check if home directory is mandated otherwise follow
  2450.          * normal course
  2451.         */
  2452.         if ( (in_homedir == NULL) || (*in_homedir == '\0') )
  2453.             is_homedir_null = TRUE;
  2454.  
  2455.         if ( (user_flags & UF_HOMEDIR_REQUIRED) && (is_homedir_null == TRUE) )
  2456.             return ERROR_INVALID_PARAMETER;
  2457.  
  2458.         if (is_homedir_null)
  2459.             {
  2460.             out_homedir[0] = '\0';
  2461.             return NERR_Success;
  2462.         }
  2463.  
  2464.         if (I_NetPathCanonicalize(NULL,
  2465.                                   in_homedir,
  2466.                                   out_homedir,
  2467.                                   outlen,
  2468.                                   NULL,
  2469.                                   &type,
  2470.                                   0L))
  2471.  
  2472.             return ERROR_INVALID_PARAMETER;
  2473.  
  2474.         if ( (type != ITYPE_PATH_ABSD) && (type != ITYPE_UNC) )
  2475.             return ERROR_INVALID_PARAMETER;
  2476.  
  2477.         return NERR_Success;
  2478. }
  2479.  
  2480.  
  2481. /*
  2482.  *      SetScriptPath
  2483.  *
  2484.  *      Purpose:    Set the user's script path field in the user
  2485.  *                  record if all the neccessary requirement are met.
  2486.  *
  2487.  *
  2488.  *      Notes:
  2489.  *                  Script path must be a relative path
  2490.  *
  2491.  *      Assumptions:
  2492.  *                  input arguments are presumed to be valid
  2493.  *
  2494. */
  2495. unsigned short
  2496. SetScriptPath(in_script, out_script, outlen)
  2497. char far *  in_script;
  2498. char far *  out_script;
  2499. unsigned short  outlen;
  2500. {
  2501.         unsigned long   type = 0;
  2502.  
  2503.         if ( (in_script == NULL) || (*in_script == '\0') )
  2504.             {
  2505.             out_script[0] = '\0';
  2506.             return NERR_Success;
  2507.         }
  2508.  
  2509.         if(I_NetPathCanonicalize(NULL,
  2510.                                  in_script,
  2511.                                  out_script,
  2512.                                  outlen,
  2513.                                  NULL,
  2514.                                  &type,
  2515.                                  0L) || (type != ITYPE_PATH_RELND) )
  2516.  
  2517.             return ERROR_INVALID_PARAMETER;
  2518.  
  2519.        return NERR_Success;
  2520. }
  2521.