home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
netusfun.zip
/
userapi.c
Wrap
C/C++ Source or Header
|
2003-03-04
|
100KB
|
2,521 lines
/*******************************************************************************/
/* SCCSID: %W% %E% */
/* */
/* */
/* OCO Source Materials */
/* */
/* Program number 5639-F93 */
/* */
/* (c) Copyright IBM Corp. 1987,1999 */
/* */
*/
/* */
/*******************************************************************************/
/*
* (C) 1994 IBM Corporation
* (P) 1994 IBM OS/2 LAN Server
*
* OCO Source Materials
*/
/* Post ISO/CMVC Revision history:
*
* Flags prefix: f = feature d = defect
*
* Flag Fixer Date Tester Date Review Date Release
* ---- -------- -------- ------- -------- ----------- ---------
* @f00 f2175 TRK 93Dec09 TRK 93Dec09 93Dec11 ls 4.0
* @d01 d6634 SYED 3-28-94
* d4701 SL 02jun94
* d9983 MEB 94Jul22 MEB 94Jul22 94Jul25 ls 4.0
* d33038 VEC 96Mar03 VEC 96Mar03 96Mar03 ls 4.0
*
* DESCRIPTIONS:
* f2175:
* WUserPasswordSet3 changes.
* d6634:
* Update last logon and last logoff in UserSetInfo.
* d4701:
* Stop checking for (unsigned variables < 0).
* d9983:
* Add the ability to set the primary computer name in the
* UserModalsSet level 101.
*
******************************************************************************
* ********* CHANGE HISTORY **************************************************
*
* Defect Flag Fixer Date Description
* ------ ----- ------ -------- ---------------------------------------
* 42799 @D05 JGC 12/12/96 Removethe change of d33038. It did no
* work. Remove the change makes it work.
* d43314 @D06 JGC 01/24/97 Remove the change of d42799, i.e., put
* back of d33038 fix.
* d43122 @D07 rcf 03/14/97 Detect change to null password
*
* f55952 @f08 lc 07/07/99 Changes to support Domain Wide UID feature
*/
/*
******************************************************************************
* USERAPI.C Second level functions for NetUser APIs
*
* The interface in this module should be same as defined
* in summary.api except that it is purely local
* (Thus there is no servername parameter).
*
* Functions:
* UAdd, UserAdd
* UserGetGroups
* UserSetGroups
* UserValidate, UserValidate2
* UserPasswordSet
* UserGetInfo
* UserSetInfo
* UserDel
* UserEnum
* UserGetModals
* UserSetModals
*
* History:
*
* 10/6/87 HongLy Changes in NetPackString
* 1. Do a NetPackString in order
* 2. Do not put a NULL pointer in variable length
* instead put a pointer to '\0';
* 12/6/87 HongLy add script
*
* 10/17/88 Pradym Many changes and additions to conform to LM1.2
* 01/25/89 Pradym Moved bunch of lower level functions to uasutil.c
*
*
* WARNING:
* A File Semaphore has been added (LOCKDBFILE,
* UNLOCKDBFILE) IT IS NECESSARY TO GRAB THIS FIRST
* BEFORE GRABBING MEMORY SEMAPHORE.
* Memory semaphore must be released before doing DISK I/O.
*
*/
#define INCL_DOSMEMMGR
#define INCL_DOSFILEMGR
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#include <os2.h>
#include <ctype.h>
#include <netcons.h>
#include <icanon.h>
#include <dos.h>
#include <netlib.h>
#include <neterr.h>
#include <shares.h>
#include <apiutil.h>
#include <inetapi.h>
#include <remutil.h>
#include <rdrioctl.h> /* next three are required for srvinfo.h */
#include <ncb.h>
#include <netbuf.h>
#include <server.h>
#include <wksta.h>
#include <api.h> /* GetServerSegs & FreeServerSegs */
#include <resstats.h>
#include <srvinfo.h>
#include <access.h>
#include <uascache.h>
#include <apisec.h>
#include <rnetapi.h>
#include <crypt.h>
#include <permit.h>
#include <acfproto.h>
#include <assert.h>
#include "uasutil.h"
API_FUNCTION FreeUserEntries(char far * username);
/*
* Local prototype
*/
static int near vcopy(char far *, char far *, int);
unsigned short SetHomeDir(unsigned short, char far *, char far *, unsigned short);
unsigned short SetScriptPath(char far *, char far *, unsigned short);
/*
* UAdd -- Add a user name
*
* Following default values are used for level 1 calls.
*
* full_name usri1_name
* usr_comment NULL
* workstations NULL (means login allowed from any)
* acct_expires TIMEQ_FOREVER (never expires)
* max_storage USER_MAXSTORAGE_UNLIMITED
* logon_hours Always
* logon_server Domain Controller (Null_String)
*
* Array containing old passwords for history checking is initialized
* to all 0xFFs in user record being added. The units_per_week is
* UNITS_PER_WEEK for this release and user passed parameter in struct
* user_info_2, if any, is ignored.
*
* Input:
* buf filled with struct user_info_X (X = Level)
* buflen size of buffer
* level level of detail (must be 1 or 2)
* home homedirectory
* script logon script
* fd net.acc file handle
*
* Output:
* 0 -- success
* NERR_GroupExists
* NERR_ACFNoRoom
* NERR_UserExists
* NERR_FileIOFail
*
*/
int
UAdd(buf, level, home, script, fd)
char far *buf;
short level;
char far *home;
char far *script;
int fd;
{
#ifndef REMONLY
int err;
struct user_object far *uo;
struct _userrec far *u;
char priv;
char far * name;
char far * passwd;
char far * comment;
char far * buf_end;
SEL sel;
unsigned short full=TRUE; /* @f08a */
unsigned short flags;
unsigned long type;
char far * p;
long pos;
long serial;
char local_uname[UNLEN+1];
if (level == LEVEL_1)
name = ((struct user_info_1 far *)buf)->usri1_name;
else
name = ((struct user_info_2 far *)buf)->usri2_name;
if (err = I_NetNameCanonicalize(NULL, name, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return ERROR_INVALID_PARAMETER;
name = local_uname;
/* Is name in group list */
if (GroupId(name, &serial) >= 0 ) /* name exists */
return NERR_GroupExists;
if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
return err;
else {
uo = (struct user_object far *) PTR(sel, 0);
u = &uo->uo_record;
buf_end = (char far *)(u + 1);
}
if (Ucb->hdr.num_users >= MAX_USERS)
err = NERR_ACFNoRoom;
else
err = GetUserObject(fd, name, uo, &pos);
if (err == 0) /* Duplicate Name */
err = NERR_UserExists;
if (err != NERR_UserNotFound)
{
DosFreeSeg(sel);
return err;
}
/* zero the "err" variable so we won't be bitten unwittingly */
err = 0;
/* Ok ! no duplicate, copy the stuff into the u record */
u->name[UNLEN] = '\0';
strncpyf(u->name, name, UNLEN);
/* common defaults for both levels */
u->last_logon = u->last_logoff = 0L; /* 0 ==> unknown */
u->bad_pw_count = u->num_logons = -1; /* -1 ==> unknown */
u->code_page = 0;
memsetf(u->logonhrs, (unsigned char) 0xFF, UNITS_PER_WEEK/8);
memsetf(u->old_passwds, (unsigned char) 0xFF,sizeof(u->old_passwds));
if (level == LEVEL_1)
{
passwd = ((struct user_info_1 far *)buf)->usri1_password;
priv = (char) ((struct user_info_1 far *)buf)->usri1_priv;
flags = ((struct user_info_1 far *)buf)->usri1_flags;
comment = ((struct user_info_1 far *)buf)->usri1_comment;
/* set defaults */
URAppend (u, &buf_end, &u->full_name_o, name, MAXCOMMENTSZ,
FALSE);
URAppend (u, &buf_end, &u->usr_comment_o, NULL, 0, FALSE);
URAppend (u, &buf_end, &u->parms_o, NULL, 0, FALSE);
URAppend (u, &buf_end, &u->workstation_o, NULL, 0, FALSE);
/* default logon_server is "" ==> domain controller */
URAppend (u, &buf_end, &u->logon_server_o, NULL, 0, FALSE);
u->acct_expires = TIMEQ_FOREVER;
u->max_storage = USER_MAXSTORAGE_UNLIMITED;
u->user.uc0_auth_flags = 0;
u->country_code = 0;
u->code_page = 0;
GetCountryCode((unsigned short far *) &u->country_code);
}
else
{
passwd = ((struct user_info_2 far *)buf)->usri2_password;
priv = (char) ((struct user_info_2 far *)buf)->usri2_priv;
flags = ((struct user_info_2 far *)buf)->usri2_flags;
comment = ((struct user_info_2 far *)buf)->usri2_comment;
/* set level 2 stuff */
if (((struct user_info_2 far *)buf)->usri2_full_name == NULL)
URAppend(u, &buf_end, &u->full_name_o, NULL, 0, FALSE);
else
URAppend(u, &buf_end, &u->full_name_o,
((struct user_info_2 far *)buf)->usri2_full_name,
MAXCOMMENTSZ, FALSE);
if (((struct user_info_2 far *)buf)->usri2_usr_comment == NULL)
URAppend(u, &buf_end, &u->usr_comment_o,
NULL, 0, FALSE);
else
{
URAppend(u, &buf_end, &u->usr_comment_o,
((struct user_info_2 far *)buf)->usri2_usr_comment,
MAXCOMMENTSZ, FALSE);
}
if (((struct user_info_2 far *)buf)->usri2_parms == NULL)
URAppend(u, &buf_end, &u->parms_o, NULL, 0, FALSE);
else
URAppend(u, &buf_end, &u->parms_o,
((struct user_info_2 far *)buf)->usri2_parms,
MAXCOMMENTSZ, FALSE);
u->acct_expires =
((struct user_info_2 far *)buf)->usri2_acct_expires;
u->max_storage =
((struct user_info_2 far *)buf)->usri2_max_storage;
/* space delimited computer names terminated by \0 */
if (((struct user_info_2 far *)buf)->usri2_workstations != NULL)
{
p = ((struct user_info_2 far *)buf)->usri2_workstations;
err = URAppend (u, &buf_end, &u->workstation_o, p,
MAXWORKSTATIONS * (CNLEN+1), TRUE);
}
else
URAppend (u, &buf_end, &u->workstation_o, NULL, 0, FALSE);
/* logon_hours == NULL ==> Access allowed at All times */
p = ((struct user_info_2 far *)buf)->usri2_logon_hours;
if ( p != NULL )
memcpyf(u->logonhrs, p, UNITS_PER_WEEK/8);
/* set the logon server if given. NULL ==> domain controller */
/* Note that \\* means any server can be used as logon server */
p = ((struct user_info_2 far *)buf)->usri2_logon_server;
if (p != NULL && p[0] != '\0')
{
if (p[0] == '\\' && p[1] == '\\' && p[2] == '*' && strlenf(p) == 3)
URAppend(u, &buf_end,&u->logon_server_o,p,UNCLEN,FALSE);
else if ( I_NetPathType(NULL, p, &type, 0L) ||
type != ITYPE_UNC_COMPNAME)
err = ERROR_INVALID_PARAMETER;
else
URAppend(u, &buf_end,&u->logon_server_o,p,UNCLEN,FALSE);
}
else
URAppend(u, &buf_end, &u->logon_server_o, NULL, 0, FALSE);
u->country_code = ((struct user_info_2 far *)buf)->usri2_country_code;
u->code_page = ((struct user_info_2 far *)buf)->usri2_code_page;
u->user.uc0_auth_flags = ((struct user_info_2 far *)buf)->usri2_auth_flags;
}
if (err)
{
DosFreeSeg(sel);
return err;
}
if (UseEncryption) {
/* encrypted password */
if (err = CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, passwd, u->passwd))
{
DosFreeSeg(sel);
return(err);
}
}
else
/* plain text password */
memcpyf(u->passwd, passwd, PWLEN + 1);
u->user.uc0_priv = priv;
if (home != NULL)
URAppend (u, &buf_end, &u->directory_o, home, PATHLEN, FALSE);
else
URAppend (u, &buf_end, &u->directory_o, NULL, 0, FALSE);
if (comment != NULL)
URAppend (u, &buf_end, &u->comment_o, comment, MAXCOMMENTSZ, FALSE);
else
URAppend (u, &buf_end, &u->comment_o, NULL, 0, FALSE);
if (script != NULL)
URAppend (u, &buf_end, &u->script_o, script, PATHLEN, FALSE);
else
URAppend (u, &buf_end, &u->script_o, NULL, 0, FALSE);
/* Warning: bit0 must be 1 for this release, enforced by UI */
u->flags = flags;
u->last = time_now();
memsetf(u->user.uc0_groups, 0, sizeof(u->user.uc0_groups));
/* level 200 add uses the supplied serial number as opposed */ /* @f08a */
/* to the next available one from the hash table. Also, set */ /* @f08a */
/* full flag to indicate serial number supplied is to be used */ /* @f08a */
if (level == LEVEL_200) /* @f08a */
{ /* @f08a */
u->user.uc0_guid.guid_serial = /* @f08a */
((struct user_info_200 far *)buf)->usri200_serial; /* @f08a */
full = FULL_USE_SERIAL; /* @f08a */
} /* @f08a */
else /* @f08a */
{ /* @f08a */
u->user.uc0_guid.guid_serial =
UserHashTbl[u->user.uc0_guid.guid_uid].uh_serial;
} /* @f08a */
/* before writing the record on disk zero the 10 resvd bytes of GUID */
memsetf(u->user.uc0_guid.guid_rsvd, 0, 10);
u->size = (char far *)buf_end - (char far *)u;
/* mark its membership in one of the special groups */
if (uo->uo_record.user.uc0_priv == USER_PRIV_ADMIN)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->AdminsId);
else if (uo->uo_record.user.uc0_priv == USER_PRIV_GUEST)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->GuestsId);
else if (uo->uo_record.user.uc0_priv == USER_PRIV_USER)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->UsersId);
pos = 0L;
if (err = WriteUserObject (fd, &pos, uo, full)) /* @f08c */
{
DosFreeSeg(sel);
return err;
}
Ucb->usercnt++;
DosFreeSeg(sel);
return 0;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if(buf || level || home || script || fd);
}
/*
* UserAdd -- Adding a user
*
* Since this is mostly a file-IO, we would not memory seg unless
* it is necessary
*
* Input:
* buf struct user_info_1 or user_info_2
* rootdir path (relative/abs) for home_dir
* level level of info being supplied
*
* Output:
* NERR_Success ( 0 )
* ERROR_INVALID_LEVEL
* NERR_BufTooSmall
* NERR_UserExists
* NERR_GroupExists
* NERR_ACFNoRoom
* NERR_ACFFileIOFail
*/
int
UserAdd(buf, rootdir, level)
char far *buf;
char far *rootdir;
short level;
{
#ifndef REMONLY
int err = 0;
int fd;
char homedir[PATHLEN+1];
char script[PATHLEN+1];
char far * name;
char far * home_dir;
char far * scriptp;
struct user_info_1 far *user = (struct user_info_1 far *)buf;
struct user_info_2 far *user2 = (struct user_info_2 far *)buf;
char tmp[MAXWORKSTATIONS * (CNLEN+1)];
unsigned short count;
unsigned short flags;
char far * workstn;
if (level == LEVEL_1)
name = ((struct user_info_1 far *)buf)->usri1_name;
else
name = ((struct user_info_2 far *)buf)->usri2_name;
/* Validate the user name */
if (I_NetNameValidate(NULL, name, NAMETYPE_USER, 0L) )
return NERR_BadUsername;
/* Validate the data */
if (err = ValidateUser(buf, level) )
return err;
if (level == LEVEL_1)
{
home_dir = ((struct user_info_1 far *)buf)->usri1_home_dir;
scriptp = ((struct user_info_1 far *)buf)->usri1_script_path;
flags = ((struct user_info_1 far *)buf)->usri1_flags;
}
else
{
home_dir = ((struct user_info_2 far *)buf)->usri2_home_dir;
scriptp = ((struct user_info_2 far *)buf)->usri2_script_path;
flags = ((struct user_info_2 far *)buf)->usri2_flags;
workstn = ((struct user_info_2 far *)buf)->usri2_workstations;
}
if ( ((level == LEVEL_2) || (level == LEVEL_200)) && workstn != NULL ) /* @f08c */
{
if (strlenf(workstn) > MAXWORKSTATIONS *(CNLEN+1))
return ERROR_INVALID_PARAMETER;
strcpyf(tmp, workstn);
if (I_NetListCanonicalize(NULL,
tmp,
LIST_DELIMITER_STR_API,
workstn,
strlenf(workstn)+1,
&count,
NULL,
0,
NAMETYPE_COMPUTER|OUTLIST_TYPE_API|
INLC_FLAGS_CANONICALIZE) ||
(count > MAXWORKSTATIONS))
{
strcpyf(workstn, tmp);
return ERROR_INVALID_PARAMETER;
}
}
if ( !(err = SetHomeDir(flags, home_dir, homedir, sizeof(homedir))) )
err = SetScriptPath(scriptp, script, sizeof(script));
if (err == NERR_Success)
{
if ((err = OpenAccount(&fd)) == NERR_Success)
{
/* add a new user record */
LOCKDBFILE();
LOCKUSEG();
err = UAdd(buf, level, homedir, script, fd);
UNLOCKUSEG();
UNLOCKDBFILE();
CloseAccount(fd);
}
}
/* restore workstation list */
if ( ((level == LEVEL_2) || (level == LEVEL_200)) && workstn != NULL ) /* @f08c */
strcpyf(workstn, tmp);
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (buf || rootdir || level)
;
}
/*
* UserGetGroups -- Get All groups name the user belongs to
*
* Input:
* Uname -- user name
* level -- level of detail
* buf
* buflen -- length of buffer
*
* Output:
* entries -- number of entries in returned buffer
* total -- number of entries available
*
* Returns:
* 0 -- success
* NERR_ACFFileIOFail
* ERROR_INVALID_LEVEL
* NERR_BufTooSmall
* ERROR_MORE_DATA
* NERR_UserNotFound
*/
int
UserGetGroups(uname, buf, buflen, entries, total)
const char far *uname;
char far *buf;
unsigned short buflen;
unsigned short far *entries;
unsigned short far *total;
{
#ifndef REMONLY
struct user_object far *uo;
SEL sel;
int err = 0;
int fd;
int avail;
char far *group;
char local_uname[UNLEN+1];
int i;
int j;
char c;
long pos;
if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return NERR_UserNotFound;
if (err = OpenAccount(&fd))
return err;
if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
{
CloseAccount(fd);
return err;
}
else
{
uo = (struct user_object far *) PTR(sel, 0);
LOCKDBFILE();
err = GetUserObject(fd, (char far *)local_uname, uo, &pos);
if (!err)
group = uo->uo_record.user.uc0_groups;
UNLOCKDBFILE();
}
if (err)
{
CloseAccount(fd);
DosFreeSeg(sel);
return err;
}
/* group is ptr to the group bit map let's enumerate it */
*entries =0;
*total = 0;
avail = buflen/sizeof(struct group_info_0);
for (i=0; i < MAXGROUP/8; i++ )
{
c = group[i];
for (j=0; j < 8; j++, c >>= 1 )
if (c & 1) { /* True */
// ASSERT((c = Ucb->group[i*8+j].name[0]) != REC_DELETE
// && c != REC_EMPTY, nprintf("Internal bug 3\n"))
if (avail > 0) {
memcpyf(buf, (char far *)&Ucb->group[i*8+j]
, sizeof(struct group_info_0) );
buf += sizeof(struct group_info_0);
avail --;
(*entries)++;
}
(*total)++;
}
}
CloseAccount(fd);
DosFreeSeg(sel);
if (*total > *entries)
return ERROR_MORE_DATA;
else
return NERR_Success;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || buf || buflen || entries || total);
}
/*
* UserSetGroups Replace existing group map of the named user
* with a new one making this user member of groups
* specified in buffer.
*
* Input:
* uname user name
* level level of detail
* buf Buffer filled with struct group_info_0
* buflen length of buffer
* entries number of entries in supplied buffer
*
* Output:
*
*
* Returns:
* 0 -- success
* NERR_ACFFileIOFail
* ERROR_INVALID_LEVEL
* NERR_BufTooSmall
* ERROR_MORE_DATA
* NERR_UserNotFound
*/
int
UserSetGroups(uname, buf, buflen, entries)
const char far *uname;
char far *buf;
unsigned short buflen;
unsigned short entries;
{
#ifndef REMONLY
struct user_object far *uo;
SEL sel;
struct group_info_0 far * gname;
int err = 0;
USER far * user;
short gid;
int fd;
long pos;
char local_uname[UNLEN+1];
if ( (buflen/sizeof(struct group_info_0)) < entries )
return NERR_BufTooSmall;
if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return NERR_UserNotFound;
if (err = OpenAccount(&fd))
return err;
if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
{
CloseAccount(fd);
return err;
}
else
uo = (struct user_object far *) PTR(sel, 0);
LOCKDBFILE();
if (err = GetUserObject(fd, (char far *)local_uname, uo, &pos))
{
UNLOCKDBFILE();
CloseAccount(fd);
DosFreeSeg(sel);
return err;
}
memsetf(uo->uo_record.user.uc0_groups, 0,
sizeof(uo->uo_record.user.uc0_groups));
gname = (struct group_info_0 far *) buf;
/* now prepare new map */
while( entries-- )
{
if (err = I_NetNameCanonicalize(NULL, gname->grpi0_name,
(char far *)gname->grpi0_name,
GNLEN+1, NAMETYPE_GROUP, 0L))
{
/* treat bad name same as Group not found */
err = NERR_GroupNotFound;
}
else if (!(GetGroupId(Ucb->group, gname->grpi0_name, &gid)))
{
/* return error if Special Group found */
if ((gid != Ucb->AdminsId) &&
(gid != Ucb->GuestsId) &&
(gid != Ucb->LocalId) &&
(gid != Ucb->UsersId))
MARKUSE(uo->uo_record.user.uc0_groups, gid);
else
err = NERR_SpeGroupOp;
}
else
err = NERR_GroupNotFound;
if (err)
{
UNLOCKDBFILE();
CloseAccount(fd);
DosFreeSeg(sel);
return err;
}
gname++;
}
/* mark its membership in one of the special groups */
if (uo->uo_record.user.uc0_priv == USER_PRIV_ADMIN)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->AdminsId);
else if (uo->uo_record.user.uc0_priv == USER_PRIV_GUEST)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->GuestsId);
else if (uo->uo_record.user.uc0_priv == USER_PRIV_USER)
MARKUSE(uo->uo_record.user.uc0_groups, Ucb->UsersId);
err = WriteUserObject (fd, &pos, uo, TRUE);
LOCKUSEG();
user = FindUidInCache (uo->uo_record.user.uc0_guid.guid_uid,
uo->uo_record.user.uc0_guid.guid_serial);
if ( err == 0 && user)
{
/* update the cache */
memcpyf(user->uc0_groups, uo->uo_record.user.uc0_groups,
sizeof(user->uc0_groups));
KickPinballSem();
}
UNLOCKUSEG();
UNLOCKDBFILE();
DosFreeSeg(sel);
CloseAccount(fd);
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || buf || buflen || entries);
}
/*
* UserPasswordSet
*
* passlen password length (when it was in plain text form)
*/
int
UserPasswordSet(uname, old, new, passlen, uo, pos, fd, clevel)
char far *uname;
char far *old; /* old password */
char far *new; /* new password */
unsigned short passlen;
struct user_object far *uo;
long far * pos;
int fd;
unsigned short clevel;
{
# define NULL_ESTD "\xaa\xd3\xb4\x35\xb5\x14\x04\xee\xaa\xd3\xb4\x35\xb5\x14\x04\xee" /*@D07*/
#ifndef REMONLY
struct _userrec far *u;
register int err = 0;
unsigned long current_time;
int saverr = 0;
int nullpw = FALSE; /*@D07*/
u = &uo->uo_record;
if (memcmpf(NULL_ESTD, new, ENCRYPTED_PWLEN)) nullpw = FALSE; /*@D07*/
else nullpw = TRUE; /*New PW is NULL*/ /*@D07*/
if /* this is NOT from a remote call to WUserPasswordSet3 */
(old) // @f00a
{
if (UseEncryption)
{
/* encrypting server, determine if it has the right */
if (CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, old, old))
return ERROR_ACCESS_DENIED;
else if (memcmpf(u->passwd, old, ENCRYPTED_PWLEN))
saverr = ERROR_INVALID_PASSWORD;
else if (CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, new, new))
return ERROR_ACCESS_DENIED;
}
else
{
/* non encrypting server */
if (strncmpf(u->passwd, old, PWLEN + 1))
saverr = ERROR_INVALID_PASSWORD;
}
}
else // @f00a
{
if (UseEncryption &&
CryptUID(ENCR_KEY, u->user.uc0_guid.guid_uid, new, new))
return ERROR_ACCESS_DENIED;
}
current_time = time_now();
/*
* Bypass all restrictions when called from NETLOGON service.
*/
if (clevel != ACCESS_NETLOGON)
{
if ((unsigned long)(u -> acct_expires) < current_time)
return NERR_AccountExpired;
if (!(u->flags & UF_PASSWD_NOTREQD)) // password is required
{
/*
* Following restrictions will be enforced only if the
* password is required i.e. UF_PASSWORD_NOTREQD flag
* is not set on this account.
*/
if (u->flags & UF_PASSWD_CANT_CHANGE)
return NERR_PasswordCantChange;
if ( (current_time - u->last) < Ucb->hdr.min_passwd_age )
return NERR_PasswordTooRecent;
if (CheckPasswdHistory(new, u->old_passwds, UseEncryption))
return NERR_PasswordHistConflict;
if (passlen < Ucb->hdr.min_passwd_len)
return NERR_PasswordTooShort;
if ((nullpw) && (0 < Ucb->hdr.min_passwd_len)) /*@D07*/
return NERR_PasswordTooShort; /*@D07*/
}
else // password is not required
{
if (passlen != IGNORE_PASSWDLEN)
{
/*
* If password is not required on this account then
* the caller can either specify a null password ("")
* or supply one whichis not shorter than minimum
* password length modal. It is relevant only for
* LM2.0 clients.
*/
if ( (passlen != 0) && (passlen < Ucb->hdr.min_passwd_len) )
return NERR_PasswordTooShort;
}
} // LM1.X clients can bypass modal restrictions
}
if (saverr)
{
/* We check other password restrictions and return those errors
* as appropriate before we return an error that the password
* sent was incorrect. We also pause for INTRUDER_DELAY (3 seconds)
* before returning to slow down hackers trying to figure out a
* password. We probably need to do an audit of this failure as
* well, but that's DCR material since it would mean defining a
* new audit entry.
*/
DosSleep(INTRUDER_DELAY);
return saverr;
}
SavePassword(u->old_passwds, u->passwd, Ucb->hdr.passwd_hist_len);
memcpyf(u->passwd, new, ENCRYPTED_PWLEN);
u->last = current_time;
LOCKDBFILE();
err = WriteUserObject(fd, pos, uo, TRUE);
UNLOCKDBFILE();
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || old || new || passlen || fd || uo || pos || clevel);
}
/*
* UserGetInfo -- Get user's Information
* Note That we will not return Password
*
* Input:
* uname - user name
* level -- level of detail {0, 1, 2, 10, 11}
* buf, buflen
* Output:
* total -- number of bytes available
*
* Returns:
* 0 -- success
* ERROR_INVALID_LEVEL
* NERR_BufTooSmall
* ERROR_MORE_DATA
* NERR_UserNotFound
*/
int
UserGetInfo(uname, level, buf, buflen, total)
char far *uname;
short level;
char far *buf;
unsigned short buflen;
unsigned short far *total;
{
#ifndef REMONLY
int fd;
struct user_info_1 far *user;
struct user_info_2 far *user2;
struct user_info_10 far *user10;
struct user_info_11 far *user11;
struct user_object far *uo;
struct _userrec far *u;
SEL sel;
unsigned short info_size; /* @f08a */
int err = 0;
int sts;
char far *fixed_size_end; /* end of fixed size data */ /* @f08a */
char far *end = buf+buflen; /* end of buffer */
long pos;
char local_uname[UNLEN+1];
if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return NERR_UserNotFound;
/* open the named file */
if (err = OpenAccount(&fd))
return err;
if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
{
CloseAccount(fd);
return err;
}
else {
uo = (struct user_object far *) PTR(sel, 0);
u = &uo->uo_record;
}
LOCKDBFILE();
sts = GetUserObject(fd, local_uname, uo, &pos);
CloseAccount(fd);
UNLOCKDBFILE();
if (sts)
{
DosFreeSeg(sel);
return sts;
}
if (level == LEVEL_0 ) {
*total = sizeof (struct user_info_0 );
if (buflen < sizeof(struct user_info_0) )
err = NERR_BufTooSmall;
else
strcpyf(buf, local_uname);
}
else if (level == LEVEL_1) {
*total = sizeof(struct user_info_1) +
strlenf( STRING(u, directory_o)) + 1 +
strlenf( STRING(u, comment_o)) + 1 +
strlenf( STRING(u, script_o)) + 1;
if (buflen < sizeof(struct user_info_1) )
err = NERR_BufTooSmall;
else {
user = (struct user_info_1 far *)buf;
strcpyf(user->usri1_name, local_uname);
strcpyf(user->usri1_password, Null_Passwd);
// @D06:begin: Put back d33038 fix.
if (u->last) // d33038
user->usri1_password_age = time_now() - u->last;
else // d33038
user->usri1_password_age = 0; // d33038
// @D06:end
user->usri1_priv = u->user.uc0_priv;
user->usri1_home_dir = STRING (u, directory_o);
NetPackString(&user->usri1_home_dir,
(char far *)(user+1), &end);
user->usri1_comment = STRING (u, comment_o);
NetPackString(&user->usri1_comment,
(char far *)(user+1), &end);
user->usri1_flags = u->flags;
user->usri1_script_path = STRING (u, script_o);
NetPackString(&user->usri1_script_path,
(char far *)(user+1), &end);
}
}
else if ((level == LEVEL_2) || (level == LEVEL_200)) { /* @f08c */
if (level == LEVEL_2) /* @f08a */
{ /* @f08a */
info_size = sizeof(struct user_info_2); /* @f08a */
} /* @f08a */
else /* @f08a */
{ /* @f08a */
info_size = sizeof(struct user_info_200); /* @f08a */
} /* @f08a */
*total = info_size + /* @f08c */
strlenf( STRING( u, directory_o)) +1 +
strlenf( STRING( u, comment_o))+1 +
strlenf( STRING( u, script_o))+1 +
strlenf( STRING( u, usr_comment_o))+1 +
strlenf( STRING( u, full_name_o))+1 +
strlenf( STRING( u, parms_o))+1 +
strlenf( STRING( u, workstation_o))+1 +
strlenf( STRING( u, logon_server_o))+1 +
UNITS_PER_WEEK/8;
if (buflen < info_size ) /* @f08c */
err = NERR_BufTooSmall;
else {
user2 = (struct user_info_2 far *)buf;
fixed_size_end = buf+info_size; /* @f08a */
strcpyf(user2->usri2_name, local_uname);
strcpyf(user2->usri2_password, Null_Passwd);
// @D06:begin: Put back d33038 fix.
if (u->last) // d33038
user2->usri2_password_age = time_now() - u->last;
else // d33038
user2->usri2_password_age = 0; // d33038
// @D06:end
user2->usri2_priv = u->user.uc0_priv;
user2->usri2_home_dir = STRING(u, directory_o);
NetPackString(&user2->usri2_home_dir,
fixed_size_end, &end); /* @f08c */
user2->usri2_comment = STRING (u, comment_o);
NetPackString(&user2->usri2_comment,
fixed_size_end, &end); /* @f08c */
user2->usri2_flags = u->flags;
user2->usri2_script_path = STRING (u, script_o);
NetPackString(&user2->usri2_script_path,
fixed_size_end, &end); /* @f08c */
user2->usri2_full_name = STRING (u, full_name_o);
NetPackString(&user2->usri2_full_name,
fixed_size_end, &end); /* @f08c */
user2->usri2_usr_comment = STRING (u, usr_comment_o);
NetPackString(&user2->usri2_usr_comment,
fixed_size_end, &end); /* @f08c */
user2->usri2_parms = STRING (u, parms_o);
NetPackString(&user2->usri2_parms,
fixed_size_end, &end); /* @f08c */
/* workstations go here */
user2->usri2_workstations = STRING (u, workstation_o);
NetPackString(&user2->usri2_workstations,
fixed_size_end, &end); /* @f08c */
user2->usri2_last_logon= u->last_logon;
user2->usri2_last_logoff = u->last_logoff;
user2->usri2_bad_pw_count = u->bad_pw_count;
user2->usri2_num_logons = u->num_logons;
user2->usri2_max_storage = u->max_storage;
user2->usri2_acct_expires = u->acct_expires;
user2->usri2_logon_hours = u->logonhrs;
NetPackBitmap(&user2->usri2_logon_hours,
fixed_size_end, &end, UNITS_PER_WEEK/8); /* @f08c */
/* logon server go here */
user2->usri2_logon_server = STRING (u, logon_server_o);
NetPackString(&user2->usri2_logon_server,
fixed_size_end, &end); /* @f08c */
user2->usri2_country_code = u->country_code;
user2->usri2_code_page = u->code_page;
user2->usri2_auth_flags = u->user.uc0_auth_flags;
user2->usri2_units_per_week = UNITS_PER_WEEK;
/* level 200 asks that we return the user's */ /* @f08a */
/* serial number as well. */ /* @f08a */
if (level == LEVEL_200) /* @f08a */
{ /* @f08a */
((struct user_info_200 far *)buf)->usri200_serial = /* @f08a */
u->user.uc0_guid.guid_serial; /* @f08a */
} /* @f08a */
}
}
else if (level == LEVEL_10) {
*total = sizeof(struct user_info_10) +
strlenf( STRING (u, comment_o))+1 +
strlenf( STRING (u, usr_comment_o))+1 +
strlenf( STRING (u, full_name_o))+1;
if (buflen < sizeof(struct user_info_10) )
err = NERR_BufTooSmall;
else {
user10 = (struct user_info_10 far *)buf;
strcpyf(user10->usri10_name, local_uname);
user10->usri10_comment = STRING (u, comment_o);
NetPackString(&user10->usri10_comment,
(char far *)(user10+1), &end);
user10->usri10_usr_comment = STRING(u, usr_comment_o);
NetPackString(&user10->usri10_usr_comment,
(char far *)(user10+1), &end);
user10->usri10_full_name = STRING(u, full_name_o);
NetPackString(&user10->usri10_full_name,
(char far *)(user10+1), &end);
}
}
else if (level == LEVEL_11) {
*total = sizeof(struct user_info_11) +
strlenf( STRING (u, comment_o))+1 +
strlenf( STRING (u, usr_comment_o))+1 +
strlenf( STRING (u, full_name_o))+1 +
strlenf( STRING (u, directory_o))+1 +
strlenf( STRING (u, logon_server_o))+1 +
strlenf( STRING (u, workstation_o))+1 +
strlenf( STRING (u, parms_o))+1 +
UNITS_PER_WEEK/8;
if (buflen < sizeof(struct user_info_11) )
err = NERR_BufTooSmall;
else {
user11 = (struct user_info_11 far *)buf;
strcpyf(user11->usri11_name, local_uname);
// @D06:begin: Put back d33038 fix.
if (u->last) // d33038
user11->usri11_password_age = time_now() - u->last;
else // d33038
user11->usri11_password_age = 0; // d33038
// @D06:end
user11->usri11_priv = u->user.uc0_priv;
user11->usri11_auth_flags = u->user.uc0_auth_flags;
user11->usri11_comment = STRING (u, comment_o);
NetPackString(&user11->usri11_comment,
(char far *)(user11+1), &end);
user11->usri11_usr_comment = STRING (u, usr_comment_o);
NetPackString(&user11->usri11_usr_comment,
(char far *)(user11+1), &end);
user11->usri11_full_name = STRING (u, full_name_o);
NetPackString(&user11->usri11_full_name,
(char far *)(user11+1), &end);
user11->usri11_home_dir = STRING (u, directory_o);
NetPackString(&user11->usri11_home_dir,
(char far *)(user11+1), &end);
user11->usri11_parms = STRING (u, parms_o);
NetPackString(&user11->usri11_parms,
(char far *)(user11+1), &end);
user11->usri11_last_logon= u->last_logon;
user11->usri11_last_logoff = u->last_logoff;
user11->usri11_bad_pw_count = u->bad_pw_count;
user11->usri11_num_logons = u->num_logons;
user11->usri11_country_code = u->country_code;
user11->usri11_code_page = u->code_page;
user11->usri11_max_storage = u->max_storage;
user11->usri11_units_per_week = UNITS_PER_WEEK;
/* logon server go here */
user11->usri11_logon_server =
STRING (u, logon_server_o);
NetPackString(&user11->usri11_logon_server,
(char far *)(user11+1), &end);
/* workstations go here */
user11->usri11_workstations = STRING(u, workstation_o);
NetPackString(&user11->usri11_workstations,
(char far *)(user11+1), &end);
user11->usri11_logon_hours = u->logonhrs;
NetPackBitmap(&user11->usri11_logon_hours,
(char far *)(user11+1), &end, UNITS_PER_WEEK/8);
}
}
DosFreeSeg(sel);
if (!err && (*total > buflen))
return ERROR_MORE_DATA;
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || level || buf || buflen || total);
}
/*
* UserSetInfo -- SetInformation
*
* Password update restrictions are enforced if the password is
* not NULL_SETINFO_PASSWORD.
*
* Input:
* uname - user name
* buf, buflen
* paramnum -- parameter number 0 (means whole structure)
* passlen length of password (when it was plain text)
* last_admin flag indicating if it is last admin account
*
* Returns:
* 0 -- success
* ERROR_INVALID_LEVEL
* NERR_BufTooSmall
* ERROR_MORE_DATA
*/
int
UserSetInfo( uname, buf, parmnum, rootdir, level, passlen, last_admin)
char far *uname;
char far *buf;
int parmnum;
char far *rootdir;
short level;
unsigned short passlen;
unsigned short last_admin;
{
#ifndef REMONLY
int fd;
struct user_info_1 far *user = (struct user_info_1 far *)buf;
struct user_info_2 far *usr2 = (struct user_info_2 far *)buf;
struct _userinfo far *u;
struct user_object far *uo;
SEL sel;
USER far *user1;
unsigned long type = 0;
unsigned short full=TRUE; /* @f08a */
unsigned short old_priv;
unsigned short new_priv;
int err = 0;
unsigned short flags;
char usr_passwd[ENCRYPTED_PWLEN];
char far * home;
char far * script;
char far * rem;
unsigned short count;
long pos;
char local_uname[UNLEN+1];
if (parmnum == U1_ALL && (err = ValidateUser(buf, level)) )
return err;
if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return NERR_UserNotFound;
/* open the named file */
if (err = OpenAccount(&fd))
return err;
if (err = DosAllocSeg(sizeof (struct _userinfo) + MAX_USER_SIZE, &sel, 0))
{
CloseAccount(fd);
return err;
}
else {
uo = (struct user_object far *)PTR(sel, 0);
u = (struct _userinfo far *) PTR(sel, MAX_USER_SIZE);
}
LOCKDBFILE();
if (err = GetUserObject (fd, local_uname, uo, &pos))
{
CloseAccount(fd);
DosFreeSeg(sel);
UNLOCKDBFILE();
return err;
}
UserExpand (u, &uo->uo_record);
/* we will allow setting fields on expired accounts */
old_priv = u->user.uc0_priv;
switch (parmnum)
{
case U1_ALL:
new_priv = ((struct user_info_1 far *)buf)->usri1_priv;
if ((old_priv == USER_PRIV_ADMIN) &&
(new_priv != USER_PRIV_ADMIN) && last_admin)
{
err = NERR_LastAdmin;
break;
}
u->user.uc0_priv = new_priv;
flags = ((struct user_info_1 far *)buf)->usri1_flags;
if ( !(flags & UF_SCRIPT) ||
((flags & ~UF_SETTABLE_BITS) != 0) )
{
err = ERROR_INVALID_PARAMETER;
break;
}
if (!(u->flags & UF_ACCOUNTDISABLE) &&
(old_priv == USER_PRIV_ADMIN) &&
(flags & UF_ACCOUNTDISABLE) && last_admin)
{
err = NERR_LastAdmin;
break;
}
u->flags = flags;
/* guest accounts can't have operator rights */
if ( (user->usri1_priv == USER_PRIV_GUEST) &&
(u->user.uc0_auth_flags) )
{
err = ERROR_INVALID_PARAMETER;
break;
}
if (level == LEVEL_1)
{
memcpyf(usr_passwd,
((struct user_info_1 far *)buf)->usri1_password,
ENCRYPTED_PWLEN);
home = ((struct user_info_1 far *)buf)->usri1_home_dir;
rem = ((struct user_info_1 far *)buf)->usri1_comment;
script =
((struct user_info_1 far *)buf)->usri1_script_path;
}
else if ((level == LEVEL_2) || (level == LEVEL_200)) /* @f08c */
{
memcpyf(usr_passwd,
((struct user_info_2 far *)buf)->usri2_password,
ENCRYPTED_PWLEN);
home = ((struct user_info_2 far *)buf)->usri2_home_dir;
rem = ((struct user_info_2 far *)buf)->usri2_comment;
script =
((struct user_info_2 far *)buf)->usri2_script_path;
/* explicitly level 2 stuff */
if (usr2->usri2_usr_comment != NULL)
strcpyf(u->usr_comment, usr2->usri2_usr_comment);
if (usr2->usri2_parms != NULL)
strcpyf(u->parms, usr2->usri2_parms);
if (usr2->usri2_full_name != NULL)
strcpyf(u->full_name, usr2->usri2_full_name);
u->acct_expires = usr2->usri2_acct_expires;
u->last_logon = usr2->usri2_last_logon; /* @d01a */
u->last_logoff = usr2->usri2_last_logoff; /* @d01a */
u->max_storage = usr2->usri2_max_storage;
if (usr2->usri2_logon_hours != NULL)
memcpyf(u->logonhrs, usr2->usri2_logon_hours,
UNITS_PER_WEEK/8);
/* workstation list handling Postponed */
if (usr2->usri2_workstations != NULL)
{
if (I_NetListCanonicalize(NULL,
usr2->usri2_workstations,
LIST_DELIMITER_STR_API,
u->workstation,
sizeof(u->workstation),
&count,
NULL,
0,
NAMETYPE_COMPUTER|
OUTLIST_TYPE_API|
INLC_FLAGS_CANONICALIZE) ||
(count > MAXWORKSTATIONS))
{
err = ERROR_INVALID_PARAMETER;
break;
}
}
/* set logon server */
/* Note that logon_server == NULL will leave present
* value of this field unchanged. logon_server name is
* expected and is stored in the form \\logonserver
*/
if (usr2->usri2_logon_server != NULL)
{
type = 0;
if (usr2->usri2_logon_server[0] == '\0')
u->logon_server[0] = '\0';
else if (I_NetPathCanonicalize( NULL,
usr2->usri2_logon_server,
u->logon_server,
UNCLEN+1,
NULL, &type, 0L) ||
((type != ITYPE_UNC_WC) && (type != ITYPE_UNC_COMPNAME)))
{
err = ERROR_INVALID_PARAMETER;
break;
}
}
u->country_code = usr2->usri2_country_code;
u->code_page = usr2->usri2_code_page;
u->user.uc0_auth_flags = usr2->usri2_auth_flags;
/* set serial number to one provided if level == 200 */ /* @f08a */
/* and serial given is different than old one. */ /* @f08a */
if ((level == LEVEL_200) && /* @f08a */
(u->user.uc0_guid.guid_serial != /* @f08a */
((struct user_info_200 far *)buf)->usri200_serial)) /* @f08a */
{ /* @f08a */
u->user.uc0_guid.guid_serial = /* @f08a */
((struct user_info_200 far *)buf)->usri200_serial; /* @f08a */
full = FULL_USE_SERIAL; /* @f08a */
} /* @f08a */
}
/*
* Following is common path for all levels
*
* Warning: Note that FLAGs have been just set to new value
* We will use new values
* allow zerolength password if notreqd bit Set
* bypass password checks for LM1.0/1.1 clients
*/
if (passlen != IGNORE_PASSWDLEN) /* Not lm1.0 case */
{
if (u->flags & UF_PASSWD_NOTREQD)
{
if ((passlen != 0) && passlen < Ucb->hdr.min_passwd_len)
{
err = NERR_PasswordTooShort;
break;
}
}
else if (passlen < Ucb->hdr.min_passwd_len)
{
err = NERR_PasswordTooShort;
break;
}
} /* end lm1.0 case */
/*
* check password update restrictions and save the
* current password for history checking
*/
if (err = UpdatePassword(u->user.uc0_guid.guid_uid, usr_passwd,
u->passwd, u->old_passwds, &u->last))
break;
if (home != NULL) { /* @P01A */
if (err = SetHomeDir(u->flags, home, u->directory, sizeof(u->directory)))
break;
} /* @P01A */
/*
* replace the old "super" group membership
* Unmark old membership first.
*/
if (old_priv == USER_PRIV_ADMIN)
MARKOFF(u->user.uc0_groups, Ucb->AdminsId);
else if (old_priv == USER_PRIV_GUEST)
MARKOFF(u->user.uc0_groups, Ucb->GuestsId);
else if (old_priv == USER_PRIV_USER)
MARKOFF(u->user.uc0_groups, Ucb->UsersId);
if (u->user.uc0_priv == USER_PRIV_ADMIN)
MARKUSE(u->user.uc0_groups, Ucb->AdminsId);
else if (u->user.uc0_priv == USER_PRIV_GUEST)
MARKUSE(u->user.uc0_groups, Ucb->GuestsId);
else if (u->user.uc0_priv == USER_PRIV_USER)
MARKUSE(u->user.uc0_groups, Ucb->UsersId);
if (rem != NULL)
strcpyf(u->comment, rem);
if (script != NULL) { /* @P01A */
err = SetScriptPath(script, u->script, sizeof(u->script));
} /* @P01A */
break;
case U1_PASSWD:
/*
* Warning: PASSWD_CANT_CHG not checked since its admin only
* Allow zerolength password if passwd_notreqd bit set
* bypass passlen checks for lm1.0 clients
*/
if (passlen != IGNORE_PASSWDLEN)
{
if (u->flags & UF_PASSWD_NOTREQD)
{
if ((passlen != 0) && passlen < Ucb->hdr.min_passwd_len)
{
err = NERR_PasswordTooShort;
break;
}
}
else if (passlen < Ucb->hdr.min_passwd_len)
{
err = NERR_PasswordTooShort;
break;
}
} /* end lm1.0 case */
err = UpdatePassword(u->user.uc0_guid.guid_uid, buf,
u->passwd, u->old_passwds, &u->last);
break;
case U1_PRIV:
/* can not change priv of last admin account */
new_priv = *(unsigned short far *)buf;
if ( (new_priv != USER_PRIV_USER) &&
(new_priv != USER_PRIV_ADMIN) &&
(new_priv != USER_PRIV_GUEST) )
{
err = ERROR_INVALID_PARAMETER;
break;
}
if ((old_priv == USER_PRIV_ADMIN) &&
(new_priv != USER_PRIV_ADMIN) && last_admin)
{
err = NERR_LastAdmin;
break;
}
if (new_priv > USER_PRIV_MAX)
err = ERROR_INVALID_PARAMETER;
else if (new_priv == USER_PRIV_GUEST && u->user.uc0_auth_flags)
err = ERROR_INVALID_PARAMETER;
else
{
u->user.uc0_priv = new_priv;
/* Unmark old membership */
if (old_priv == USER_PRIV_ADMIN)
MARKOFF(u->user.uc0_groups, Ucb->AdminsId);
else if (old_priv == USER_PRIV_GUEST)
MARKOFF(u->user.uc0_groups, Ucb->GuestsId);
else if (old_priv == USER_PRIV_USER)
MARKOFF(u->user.uc0_groups, Ucb->UsersId);
/* mark new membership */
if (u->user.uc0_priv == USER_PRIV_ADMIN)
MARKUSE(u->user.uc0_groups, Ucb->AdminsId);
else if (u->user.uc0_priv == USER_PRIV_GUEST)
MARKUSE(u->user.uc0_groups, Ucb->GuestsId);
else if (u->user.uc0_priv == USER_PRIV_USER)
MARKUSE(u->user.uc0_groups, Ucb->UsersId);
}
break;
case U1_DIR:
err = SetHomeDir(u->flags, buf, u->directory, sizeof(u->directory));
break;
case U1_COMMENT:
err = vcopy(u->comment, buf, sizeof(u->comment));
break;
case U1_USER_FLAGS:
flags = *((unsigned short far *)buf);
if ( !(flags & UF_SCRIPT) ||
((flags & ~UF_SETTABLE_BITS) != 0) )
err = ERROR_INVALID_PARAMETER;
else if (!(u->flags & UF_ACCOUNTDISABLE) &&
(old_priv == USER_PRIV_ADMIN) &&
(flags & UF_ACCOUNTDISABLE) && last_admin )
err = NERR_LastAdmin;
if (!err)
u->flags = flags;
break;
case U1_SCRIPT_PATH:
err = SetScriptPath(buf, u->script, sizeof(u->script));
break;
case PARMNUM_USR_COMMENT:
err = vcopy(u->usr_comment, buf, sizeof(u->usr_comment));
break;
case PARMNUM_PARMS:
err = vcopy(u->parms, buf, sizeof(u->parms));
break;
case PARMNUM_FULL_NAME:
/* should we also check the full name for valid characters */
err = vcopy(u->full_name, buf, sizeof(u->full_name));
break;
case PARMNUM_WORKSTATIONS:
if (I_NetListCanonicalize(NULL,
buf,
LIST_DELIMITER_STR_API,
u->workstation,
sizeof(u->workstation),
&count,
NULL, 0,
NAMETYPE_COMPUTER|OUTLIST_TYPE_API|
INLC_FLAGS_CANONICALIZE) ||
(count > MAXWORKSTATIONS))
err = ERROR_INVALID_PARAMETER;
break;
case PARMNUM_ACCT_EXPIRES:
u->acct_expires = *(long far *)buf;
break;
case PARMNUM_MAX_STORAGE:
u->max_storage = *(long far *)buf;
break;
case PARMNUM_LOGON_HOURS:
memcpyf(u->logonhrs, buf, sizeof(u->logonhrs));
break;
case PARMNUM_LOGON_SERVER:
type = 0;
if (buf[0] == '\0')
u->logon_server[0] = '\0';
else if (I_NetPathCanonicalize( NULL,
buf,
u->logon_server, UNCLEN+1,
NULL, &type, 0L) ||
((type != ITYPE_UNC_WC) &&
(type != ITYPE_UNC_COMPNAME)))
err = ERROR_INVALID_PARAMETER;
break;
case PARMNUM_COUNTRY_CODE:
u->country_code = *((unsigned short far *)buf);
break;
case PARMNUM_AUTH_FLAGS:
if ((*((unsigned short far *)buf) & ~(AF_SETTABLE_BITS)) != 0)
err = ERROR_INVALID_PARAMETER;
else if (old_priv == USER_PRIV_GUEST)
err = ERROR_INVALID_PARAMETER;
else
u->user.uc0_auth_flags = *(unsigned long far *)buf;
break;
case PARMNUM_LAST_LOGON:
u->last_logon = *(long far *)buf;
break;
case PARMNUM_LAST_LOGOFF:
u->last_logoff = *(long far *)buf;
break;
case PARMNUM_BADPW_COUNT:
u->bad_pw_count = *(unsigned short far *)buf;
break;
case PARMNUM_NUM_LOGONS:
u->num_logons = *(unsigned short far *)buf;
break;
case PARMNUM_CODE_PAGE:
u->code_page = *(unsigned short far *)buf;
break;
case PARMNUM_PASSWD_EXPIRED:
if ((int *)*buf)
u->last = 0L;
else /* only reset the time if we marked it expired */
if (!u->last)
u->last = time_now();
break;
default:
err = ERROR_INVALID_PARAMETER;
}
if (! err)
{
UserCompress (&uo->uo_record, u);
if (err = WriteUserObject (fd, &pos, uo, full)) /* @f08c */
;
else
{
LOCKUSEG();
if (user1 = FindUidInCache(u->user.uc0_guid.guid_uid,
u->user.uc0_guid.guid_serial))
{
/* update account privs and operator rights */
user1->uc0_priv = u->user.uc0_priv;
user1->uc0_auth_flags = u->user.uc0_auth_flags;
/* copy new group bitmap */
memcpyf(user1->uc0_groups, u->user.uc0_groups, MAXGROUP/8);
/* LM20 server looks in UAS cache for priv info */
KickPinballSem();
}
UNLOCKUSEG();
}
}
UNLOCKDBFILE();
DosFreeSeg(sel);
CloseAccount(fd);
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || buf || parmnum || rootdir || level || passlen || last_admin)
;
}
/*
* UserDel -- Delete a named user
*
* Input:
* uname username
* last_admin if set implies that there is only 1 admin left
* Returns:
*
* 0 -- success
* NERR_UserNotFound
* NERR_ACFFileIOFail
*/
int
UserDel(uname, last_admin)
char far *uname;
unsigned short last_admin;
{
#ifndef REMONLY
int fd;
int err = 0; /* assume no error */
struct user_object far *uo;
SEL sel;
unsigned short eread;
unsigned short etotal;
unsigned short size;
struct session_info_10 far * sessinfo;
char tmp[UNCLEN+1];
long pos;
struct user_cache_0 far *user;
char local_uname[UNLEN+1];
if (err = I_NetNameCanonicalize(NULL, uname, (char far *)local_uname,
sizeof(local_uname), NAMETYPE_USER, 0L))
return NERR_UserNotFound;
if (err = OpenAccount(&fd))
return err;
if (err = DosAllocSeg(MAX_USER_SIZE, &sel, 0))
{
CloseAccount(fd);
return err;
}
else
uo = (struct user_object far *) PTR(sel, 0);
LOCKDBFILE();
if (err = GetUserObject (fd, local_uname, uo, &pos))
; /* name not found */
else if (((uo->uo_record.user.uc0_priv & USER_PRIV_MASK) == USER_PRIV_ADMIN) && !(uo->uo_record.flags & UF_ACCOUNTDISABLE) && last_admin)
err = NERR_LastAdmin;
else if (AccessRemoveId(uo->uo_record.user.uc0_guid.guid_uid,
uo->uo_record.user.uc0_guid.guid_serial))
err = NERR_ACFFileIOFail;
else {
/* purge this users record from the cache */
if (DeleteUserObject(fd, pos, uo) != 0)
err = NERR_ACFFileIOFail;
else {
LOCKUSEG();
if (user = FindUidInCache(
uo->uo_record.user.uc0_guid.guid_uid,
uo->uo_record.user.uc0_guid.guid_serial))
{
PurgeUserRecord(user);
}
Ucb->usercnt --; /* Update counter */
KickPinballSem();
UNLOCKUSEG();
}
}
if (fd >=0 )
CloseAccount(fd);
DosFreeSeg(sel);
UNLOCKDBFILE();
if (err)
return err;
/* Tell any netlogon service that is around about this user
* being deleted so that the logon tables can be updated. This
* function lives in api\ssi\ssiutil.c. It's a side affect
* so we don't care about errors.
*/
FreeUserEntries(local_uname);
/* quit if server is not running */
if (GetServerSegs())
return NERR_Success;
else
FreeServerSegs();
/*
* All sessions belonging to this user are deleted.
* Note that we map evry error to InternalError since we
* have already deleted the user's record in the database and
* removed him from the cache.
*
* Warning: if you try to delete your own account on a remote
* server, provided you have privs to do that, your
* session will be deleted and most likely you will
* get VC_DISCONNECTED error from redir since the
* transaction never got completed.
*/
err = NetSessionEnum(NULL, 10, NULL, 0, &eread, &etotal);
if (err == NERR_BufTooSmall || err == ERROR_MORE_DATA || err == 0)
{
if (etotal == 0)
return NERR_Success;
/* get the worst case size estimate */
size = sizeof(struct session_info_10) + (UNLEN+1) + (CNLEN+1);
size *= etotal;
if (err = DosAllocSeg(size, &sel, 0))
return NERR_InternalError;
else
sessinfo = (struct session_info_10 far *) PTR(sel, 0);
}
if (NetSessionEnum(NULL, 10, (char far *) sessinfo, size, &eread, &etotal))
{
DosFreeSeg(sel);
return NERR_InternalError;
}
/* walk through the buffer looking for name of this user */
while (etotal --)
{
if (!I_NetNameCompare(NULL, local_uname, sessinfo->sesi10_username,
NAMETYPE_USER, 0L))
{
strcpyf(tmp, "\\\\");
strcatf(tmp, sessinfo->sesi10_cname);
if (WSessionDel(NULL, tmp, 0, NULL, ACCESS_LOCAL))
break;
}
sessinfo++;
}
DosFreeSeg(sel);
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (uname || last_admin);
}
/*
* Vcopy -- Verify the length and copy
*/
static int near
vcopy(to, from, size)
char far *to;
char far *from;
int size;
{
int len;
if ((len = strlenf(from) ) >= size)
return ERROR_INVALID_PARAMETER;
memcpyf(to, from, len+1);
return 0;
}
/**** UserGetModals
*
* Purpose: Get global User Modals
*
* Entry: level level of details requested (MBZ for LM1.2)
* buf buffer to return data in
* buflen size of buffer must be at least sizeof struct
* total total bytes available
*
* Exit: buffer filled with struct user_modals_info_0
*
* Return: NERR_Success or OS/2 error as appropriate
*
* NOTE: This function will succeed even though UAS may not be
* running but a good access database (net.acc) exists.
*
*/
int
UserGetModals(level, buf, buflen, total)
short level;
char far * buf;
unsigned short buflen;
unsigned short far * total;
{
#ifndef REMONLY
int fd = 0; // Jay Fix for SA
int errfd = 0 ; // Jay Fix for SA
int err = 0;
long pos;
unsigned short bytesread;
char far * end;
char hdrbuf[sizeof(struct _ahdr)];
struct user_modals_info_0 far *m;
struct user_modals_info_1 far *p;
struct user_modals_info_101 far *p1;
struct _ahdr far *h;
end = buf + buflen;
if (Ucb == NULL)
errfd = OpenAccountSpecial(&fd);
else
errfd = OpenAccount(&fd);
if (errfd == NERR_Success)
{
if (Ucb != NULL)
LOCKDBFILE();
if ((err = DosChgFilePtr(fd, 0L, 0, &pos)))
;
else if ((err = DosRead(fd, hdrbuf, sizeof(struct _ahdr),
&bytesread)) || bytesread != sizeof(struct _ahdr))
err = err ? err : NERR_ACFFileIOFail;
else
h = (struct _ahdr far *) hdrbuf;
if (Ucb != NULL)
UNLOCKDBFILE();
}
else // Jay Fix for SA
return errfd; // Jay Fix for SA
if (err)
{
CloseAccount(fd);
return err;
}
if (level == LEVEL_0)
{
m = (struct user_modals_info_0 far *)buf;
*total = sizeof(struct user_modals_info_0);
if (buflen < sizeof(struct user_modals_info_0))
{
CloseAccount(fd);
return NERR_BufTooSmall;
}
m->usrmod0_min_passwd_len = h->min_passwd_len;
m->usrmod0_max_passwd_age = h->max_passwd_age;
m->usrmod0_min_passwd_age = h->min_passwd_age;
m->usrmod0_force_logoff = h->force_logoff;
m->usrmod0_password_hist_len = h->passwd_hist_len;
m->usrmod0_maxbadpw = h->max_bad_passwd;
}
else if (level == LEVEL_1)
{
*total = sizeof(struct user_modals_info_1) +
strlenf(h->primary.uas0_computer) + 1;
if (buflen < sizeof(struct user_modals_info_1))
{
CloseAccount(fd);
return NERR_BufTooSmall;
}
p = (struct user_modals_info_1 far *)buf;
p->usrmod1_role = h->role;
p->usrmod1_primary = h->primary.uas0_computer;
NetPackString(&p->usrmod1_primary, (char far *)(p+1), &end);
if (*total > buflen)
err = ERROR_MORE_DATA;
}
else if (level == LEVEL_100)
{
*total = sizeof(struct user_modals_info_100);
if (buflen < sizeof(struct user_modals_info_100))
{
CloseAccount(fd);
return NERR_BufTooSmall;
}
memcpyf(((struct user_modals_info_100 far *)buf)->usrmod100_DBIdInfo,
h->DBIdInfo, DBIDINFO_SIZE);
}
else if (level == LEVEL_101)
{
*total = sizeof(struct user_modals_info_101) +
strlenf(h->local.uas0_computer) + 1 +
strlenf(h->primary.uas0_computer) + 1;
if (buflen < sizeof(struct user_modals_info_101))
{
CloseAccount(fd);
return NERR_BufTooSmall;
}
p1 = (struct user_modals_info_101 far *)buf;
p1->usrmod101_local_date = h->local.uas0_time_created;
p1->usrmod101_local_counter = h->local.uas0_serial_number;
p1->usrmod101_primary_date = h->primary.uas0_time_created;
p1->usrmod101_primary_counter = h->primary.uas0_serial_number;
p1->usrmod101_local_computer = h->local.uas0_computer;
NetPackString(&p1->usrmod101_local_computer,
(char far *)(p1+1), &end);
p1->usrmod101_primary_computer = h->primary.uas0_computer;
NetPackString(&p1->usrmod101_primary_computer,
(char far *)(p1+1), &end);
if (*total > buflen)
err = ERROR_MORE_DATA;
}
CloseAccount(fd);
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (level || buf || buflen || total);
}
/**** UserSetModals
*
* Purpose: Set global User Modals
*
* Entry: level level of details requested (MBZ for LM1.2)
* buf filled with struct user_modals_info_0
* buflen size of buffer
* parmnum ordinal number of parameter to set
*
* Exit: appropriate fields in net.acc and cache (conditional)
* modified
*
* Return: NERR_Success or OS/2 error as appropriate
*
* NOTE: This function will succeed at level 0 even though UAS may
* not be running but a good access database (net.acc) exists.
*
*/
int
UserSetModals(level, buf, buflen, parmnum)
short level;
char far * buf;
unsigned short buflen;
short parmnum;
{
#ifndef REMONLY
int err, fd;
long new;
unsigned short written;
unsigned short bytesread;
unsigned short role;
struct user_modals_info_0 far *m;
char far * primary;
struct _ahdr far *p;
char hdrbuf[sizeof(struct _ahdr)];
char tmpbuf[CNLEN+1];
if (Ucb == NULL)
err = OpenAccountSpecial(&fd);
else
err = OpenAccount(&fd);
if (err == NERR_Success)
{
if (Ucb != NULL)
LOCKDBFILE();
if ((err = DosChgFilePtr(fd, 0L, 0, &new)))
;
else if ((err = DosRead(fd, hdrbuf, sizeof(struct _ahdr),
&bytesread)) || bytesread != sizeof(struct _ahdr))
err = err ? err : NERR_ACFFileIOFail;
else
p = (struct _ahdr far *) hdrbuf;
if (Ucb != NULL)
UNLOCKDBFILE();
}
if (err)
{
CloseAccount(fd);
return err;
}
if (Ucb != NULL)
LOCKDBFILE();
if (level == LEVEL_0)
{
switch(parmnum)
{
case MODAL0_PARMNUM_ALL:
m = (struct user_modals_info_0 far *)buf;
// if (m->usrmod0_min_passwd_len < 0 ||
if (m->usrmod0_min_passwd_len > PWLEN)
{
err = ERROR_INVALID_PARAMETER;
break;
}
else
p->min_passwd_len = m->usrmod0_min_passwd_len;
if ((m->usrmod0_max_passwd_age < ONE_DAY) ||
(m->usrmod0_max_passwd_age < m->usrmod0_min_passwd_age))
{
err = ERROR_INVALID_PARAMETER;
break;
}
p->max_bad_passwd = m->usrmod0_maxbadpw;
p->max_passwd_age = m->usrmod0_max_passwd_age;
p->min_passwd_age = m->usrmod0_min_passwd_age;
p->force_logoff = m->usrmod0_force_logoff;
// if (m->usrmod0_password_hist_len < 0 ||
if (m->usrmod0_password_hist_len > DEF_MAX_PWHIST)
err = ERROR_INVALID_PARAMETER;
else
p->passwd_hist_len = m->usrmod0_password_hist_len;
break;
case MODAL0_PARMNUM_MIN_LEN:
// if (*(unsigned short far *)buf < 0 ||
if (*(unsigned short far *)buf > PWLEN)
err = ERROR_INVALID_PARAMETER;
else
p->min_passwd_len = *(unsigned short far *)buf;
break;
case MODAL0_PARMNUM_MAX_AGE:
if ((p->min_passwd_age > *(unsigned long far *)buf) ||
(*(unsigned long far *)buf < ONE_DAY))
err = ERROR_INVALID_PARAMETER;
else
p->max_passwd_age = *(unsigned long far *)buf;
break;
case MODAL0_PARMNUM_MIN_AGE:
if (p->max_passwd_age < *(unsigned long far *)buf)
err = ERROR_INVALID_PARAMETER;
else
p->min_passwd_age = *(unsigned long far *)buf;
break;
case MODAL0_PARMNUM_FORCEOFF:
p->force_logoff = *(unsigned long far *)buf;
break;
case MODAL0_PARMNUM_HISTLEN:
// if (*(unsigned short far *)buf < 0 ||
if (*(unsigned short far *)buf > DEF_MAX_PWHIST)
err = ERROR_INVALID_PARAMETER;
else
p->passwd_hist_len = *(unsigned short far *)buf;
break;
case MODAL0_PARMNUM_MAX_BADPW:
p->max_bad_passwd = *(unsigned short far *)buf;
break;
default:
err = ERROR_INVALID_PARAMETER;
}
}
else if (level == LEVEL_1)
{
if (parmnum == MODAL1_PARMNUM_ALL)
{
primary = ((struct user_modals_info_1 far *)buf)->usrmod1_primary;
role = ((struct user_modals_info_1 far *)buf)->usrmod1_role;
}
else if (parmnum == MODAL1_PARMNUM_PRIMARY)
primary = buf;
else if (parmnum == MODAL1_PARMNUM_ROLE)
role = *(unsigned short far *)buf;
if (parmnum == MODAL1_PARMNUM_ALL || parmnum == MODAL1_PARMNUM_ROLE)
{
if ((role != UAS_ROLE_PRIMARY) &&
(role != UAS_ROLE_MEMBER) &&
(role != UAS_ROLE_BACKUP) &&
(role != UAS_ROLE_STANDALONE))
err = ERROR_INVALID_PARAMETER;
else
p->role = role;
}
if (parmnum == MODAL1_PARMNUM_ALL || parmnum == MODAL1_PARMNUM_PRIMARY)
{
if (primary == NULL)
;
else if (primary[0] == '\0')
p->primary.uas0_computer[0] = '\0';
else
{
if (I_NetNameCanonicalize(NULL,
primary,
tmpbuf, /* output buffer */
CNLEN+1, /* sizeof output buf */
NAMETYPE_COMPUTER,
0L))
err = ERROR_INVALID_PARAMETER;
else
strcpyf(p->primary.uas0_computer, tmpbuf);
}
}
}
else if (level == LEVEL_100)
{
memcpyf(p->DBIdInfo,
((struct user_modals_info_100 far *)buf)->usrmod100_DBIdInfo,
DBIDINFO_SIZE);
}
else if (level == LEVEL_101)
{
/* WARNING: special case for internal use, see uasuser.c */
p->local.uas0_time_created =
((struct user_modals_info_101 far *)buf)->usrmod101_local_date;
p->local.uas0_serial_number =
((struct user_modals_info_101 far *)buf)->usrmod101_local_counter;
p->primary.uas0_time_created =
((struct user_modals_info_101 far *)buf)->usrmod101_primary_date;
p->primary.uas0_serial_number =
((struct user_modals_info_101 far *)buf)->usrmod101_primary_counter;
/* NULL primary name means the caller does not want to
* change the primary. It is the responsibility of the
* caller to make that decision.
*/
if ( ( ((struct user_modals_info_101 far *)buf)->usrmod101_primary_computer) != NULL) /*d9983*/
strcpyf(p->primary.uas0_computer, /*d9983*/
((struct user_modals_info_101 far *)buf)->usrmod101_primary_computer ); /*d9983*/
}
/* Update disk record: update cache if disk update OK */
if (err == NERR_Success)
{
if (!(err = DosChgFilePtr(fd, 0L, 0, &new)))
err = DosWrite(fd, (char far *) hdrbuf, sizeof(struct _ahdr), &written);
if (err || (written != sizeof(struct _ahdr)))
err = err ? err : NERR_ACFFileIOFail;
}
if (Ucb != NULL && err == NERR_Success)
{
/* copy the new information in cache if UAS running */
LOCKUSEG();
if (level == LEVEL_0)
{
switch(parmnum)
{
case MODAL0_PARMNUM_ALL:
memcpyf((char far *) &Ucb->hdr, (char far *)p, sizeof(struct _ahdr));
break;
case MODAL0_PARMNUM_MIN_LEN:
Ucb->hdr.min_passwd_len = p->min_passwd_len;
break;
case MODAL0_PARMNUM_MAX_AGE:
Ucb->hdr.max_passwd_age = p->max_passwd_age;
break;
case MODAL0_PARMNUM_MIN_AGE:
Ucb->hdr.min_passwd_age = p->min_passwd_age;
break;
case MODAL0_PARMNUM_FORCEOFF:
Ucb->hdr.force_logoff = p->force_logoff;
break;
case MODAL0_PARMNUM_HISTLEN:
Ucb->hdr.passwd_hist_len = p->passwd_hist_len;
break;
case MODAL0_PARMNUM_MAX_BADPW:
Ucb->hdr.max_bad_passwd = p->max_bad_passwd;
break;
}
}
else if (level == LEVEL_1)
{
Ucb->hdr.role = p->role;
strcpyf(Ucb->hdr.primary.uas0_computer, p->primary.uas0_computer);
if (Ucb->hdr.role == UAS_ROLE_PRIMARY || Ucb->hdr.role == UAS_ROLE_STANDALONE)
Ucb->UpdatesOK = TRUE;
else
Ucb->UpdatesOK = FALSE;
}
else if (level == LEVEL_100)
memcpyf(Ucb->hdr.DBIdInfo, p->DBIdInfo, DBIDINFO_SIZE);
else if (level == LEVEL_101)
{
/* WARNING: special case for internal use, see uasuser.c */
Ucb->hdr.local.uas0_time_created = p->local.uas0_time_created;
Ucb->hdr.local.uas0_serial_number = p->local.uas0_serial_number;
Ucb->hdr.primary.uas0_time_created = p->primary.uas0_time_created;
Ucb->hdr.primary.uas0_serial_number = p->primary.uas0_serial_number;
}
UNLOCKUSEG();
}
CloseAccount(fd);
if (Ucb != NULL)
UNLOCKDBFILE();
return err;
#else
return ERROR_NOT_SUPPORTED;
#endif /* REMONLY */
/* quiet the compiler */
if (level || buf || buflen || parmnum)
;
}
#ifdef LOCKOUT
/*
* TrackBadPasswords
* The purpose of this function is to bump the bad_pw_count
* field in user's record and disable his account (lock out)
* if bad password attempts have exceeded beyond the limit
* specified by reserved1 modal. If the password matched
* correctly and account was still enabled i.e. not locked
* out, bad password count will be reset to 0. Bad password
* tries are counted even though the account may have been
* locked out. Note that last Admin account will never be
* locked out.
*
* Entry:
* u struct _userrec far *
* fd file handle of UAS database
*
* Exit:
*
*
*/
void
TrackBadPasswords(passwd_match, fd, u, wkstn)
int passwd_match;
int fd;
struct _userrec far *u;
char far * wkstn;
{
unsigned short err = 0;
unsigned short dummy;
unsigned short total;
unsigned short last_admin = FALSE;
if (passwd_match)
{
if (u->flags & UF_ACCOUNTDISABLE)
return;
else
u->bad_pw_count = 0;
}
else
{
(u->bad_pw_count)++;
/* disable the account if we exceed reserved1 and it's active*/
if (!(u->flags & UF_ACCOUNTDISABLE))
{
if (u->bad_pw_count > Ucb->hdr.reserved1)
{
/* do not disable the last Admin account */
if ((u->user.uc0_priv & USER_PRIV_MASK) == USER_PRIV_ADMIN)
{
if (!IsLastActiveUser(u->name, ADMINGROUP, &total))
u->flags |= UF_ACCOUNTDISABLE;
}
}
}
}
/* update the bad_pw_count field reset or bump as the case maybe */
WriteUserRec(fd, &u->user, TRUE);
audit_alert_lockout(last_admin, u->name, wkstn);
}
#endif /* LOCKOUT */
/*
* SetHomeDir
*
* Purpose: Set the user's home directory field in the user
* record if all the neccessary requirement are met.
*
*
* Notes:
* If the user's account has UF_HOMEDIR_REQD flag set
* then a valid absolute path (local or unc) must be
* supplied for the home directory field. A null string
* is not a valid path. In case of NetUserSetInfo with
* zero parmnum the newly supplied flags are used for
* verifying the restrictions whereas in case of non zero
* parmnum the flgas stored in user's account are used.
*
* Assumptions:
* input arguments are presumed to be valid
*
*/
unsigned short
SetHomeDir(user_flags, in_homedir, out_homedir, outlen)
unsigned short user_flags;
char far * in_homedir;
char far * out_homedir;
unsigned short outlen;
{
unsigned long type = 0;
unsigned short is_homedir_null = FALSE;
/*
* check if home directory is mandated otherwise follow
* normal course
*/
if ( (in_homedir == NULL) || (*in_homedir == '\0') )
is_homedir_null = TRUE;
if ( (user_flags & UF_HOMEDIR_REQUIRED) && (is_homedir_null == TRUE) )
return ERROR_INVALID_PARAMETER;
if (is_homedir_null)
{
out_homedir[0] = '\0';
return NERR_Success;
}
if (I_NetPathCanonicalize(NULL,
in_homedir,
out_homedir,
outlen,
NULL,
&type,
0L))
return ERROR_INVALID_PARAMETER;
if ( (type != ITYPE_PATH_ABSD) && (type != ITYPE_UNC) )
return ERROR_INVALID_PARAMETER;
return NERR_Success;
}
/*
* SetScriptPath
*
* Purpose: Set the user's script path field in the user
* record if all the neccessary requirement are met.
*
*
* Notes:
* Script path must be a relative path
*
* Assumptions:
* input arguments are presumed to be valid
*
*/
unsigned short
SetScriptPath(in_script, out_script, outlen)
char far * in_script;
char far * out_script;
unsigned short outlen;
{
unsigned long type = 0;
if ( (in_script == NULL) || (*in_script == '\0') )
{
out_script[0] = '\0';
return NERR_Success;
}
if(I_NetPathCanonicalize(NULL,
in_script,
out_script,
outlen,
NULL,
&type,
0L) || (type != ITYPE_PATH_RELND) )
return ERROR_INVALID_PARAMETER;
return NERR_Success;
}