DEFINITION MODULE MultiUserD; (*$ Implementation:=FALSE *) (* Frank J. Beckmann 22.10.1993 *) FROM SYSTEM IMPORT ADDRESS; FROM ExecD IMPORT MinNode, TaskPtr, MsgPortPtr, Message; FROM UtilityD IMPORT tagUser; CONST multiUserName="multiuser.library"; (* Reserved users/groups WARNING: a uid may NOT be zero, a gid may be zero *) CONST ownerNobody=0; ownerSystem=MAX(LONGCARD); rootUid=MAX(CARDINAL); rootGid=MAX(CARDINAL); nobodyUid=0; useridsize=32; groupidsize=32; passwordsize=32; usernamesize=220; groupnamesize=220; homedirsize=256; (* Password File For each user, the Password File must contain a line like this: |||||| with: User Login ID (max. muUSERIDSIZE-1 characters) Encrypted Password User Number (1 - 65535) Primary Group Number (0 - 65535) Full User Name (max. muUSERNAMESIZE-1 characters) Home directory (max. muHOMEDIRSIZE-1 characters) Default Shell (not used yet, AS225 compatibility) *) CONST passwdFileName="passwd"; (* for AS225 compatibility *) (* Group File This file gives more information about the groups and defines the secondary groups (other than the primary group) a user belongs to. It exists out of two parts, separated by a blank line. The first part contains lines with the format: ||| with: Group short ID (max. muGROUPIDSIZE-1 characters) Group Number (0 - 65535) User Number of this group's manager, 0 for no manager. A group's manager must not belong to the group. Full Group Name (max. muGROUPNAMESIZE-1 characters) NOTE: Not every group must have a line in this file, but at least one group must have one. The seconds part contains lines with the format: :[,...] with: User Number (1 - 65535) Group Number (0 - 65535) If you think you'll exceed the maximum line length (circa 1K), you may use more than one line per user. *) CONST groupFileName="MultiUser.group"; (* Configuration File This file contains lines with options in the form =. 0 is used for OFF, 1 for ON. Defaults to the values between square brackets. LIMITDOSSETPROTECTION dos.library/SetProtection() cannot change protection bits for GROUP and OTHER [1] PROFILE execute the Profile if it exists [1] LASTLOGINREQ display the Lastlogin requester [1] LOGSTARTUP log startup [0] LOGLOGIN log successful logins [0] LOGLOGINFAIL log failed logins [0] LOGPASSWD log successful password changes [0] LOGPASSWDFAIL log failed password changes [0] LOGCHECKPASSWD log successful password checks [0] LOGCHECKPASSWDFAIL log failed password checks [0] PASSWDUIDLEVEL users with a uid greather than or equal to can change their passwords [0] PASSWDGIDLEVEL users with a gid greather than or equal to can change their passwords [0] NOTE: if a user has a uid less than the PASSWDUIDLEVEL AND a gid less than PASSWDGIDLEVEL he/she is NOT allowed to change his/her password! *) CONST configFileName="MultiUser.config"; (* Log File *) CONST logFileName="MultiUser.log"; (* Lastlogin File *) CONST lastLoginFileName=".lastlogin"; (* Profile *) CONST profileFileName=".profile"; (* Plan file *) CONST planFileName=".plan"; (* Key File This file must be present in the root directory of every volume that uses the MultiUserFileSystem. It must contain 3 lines: - a pseudo random ASCII key (max. 1023 characters). - the directory of the password file, if located on this volume, otherwise an empty line (no spaces!). e.g. ":inet/db" for AS225 compatibility - the directory of the configuration file, if located on this volume, otherwise an empty line (no spaces!). e.g. ":MultiUser" If there is ANY inconsistency the system will refuse to work!! *) CONST keyFileName=":.MultiUser.keyfile"; (* Tags for muLogoutA() muLoginA() muSetDefProtectionA() *) TYPE muTags=( muInput:=tagUser+1, (* filehandle - default is Input() *) muOutput, (* filehandle - default is Output() *) muGraphical, (* boolean - default is FALSE *) muPubScrName, (* name of public screen *) muTask, (* task (NOT the name!!) *) muOwn, (* make a task owned by this user *) muGlobal, (* change it for all tasks on the *) (* same level as this one *) muQuiet, (* for muLogoutA(), don't give a *) (* login prompt, simply logout *) muUserID, (* UserID for muLoginA(), must be *) (* used together with muT_Password!! *) muPassword, (* Password for muLoginA(), must be *) (* used together with muT_UserID!! *) muDefProtection, (* Default protection bits *) (* default is RWED GROUP R OTHER R *) muAll (* for muLogoutA(), logout until *) (* user stack is empty *) ); (* Public User Information Structure For future compatibility, you should ALWAYS use muAllocUserInfo() to allocate this structure. NEVER do it by yourself!! *) TYPE UserInfo=RECORD userID: ARRAY [0..useridsize-1] OF CHAR; uid: CARDINAL; gid: CARDINAL; userName: ARRAY [0..usernamesize-1] OF CHAR; homeDir: ARRAY [0..homedirsize-1] OF CHAR; numSecGroups: CARDINAL; (* Number of Secondary Groups this *) (* user belongs to *) secGroups: ADDRESS; (* POINTER TO ARRAY OF CARDINAL *) (* Points to an array of NumSecGroups *) (* Secondary Group Numbers *) END; UserInfoPtr=POINTER TO UserInfo; (* Public Group Information Structure For future compatibility, you should ALWAYS use muAllocGroupInfo() to allocate this structure. NEVER do it by yourself!! *) TYPE GroupInfo=RECORD groupID: ARRAY [0..groupidsize-1] OF CHAR; gid: CARDINAL; mgrUid: CARDINAL; (* Manager of this group *) groupName: ARRAY [0..groupnamesize-1] OF CHAR; END; GroupInfoPtr=POINTER TO GroupInfo; (* KeyTypes for muGetUserInfo() muGetGroupInfo() *) CONST keyTypeFirst=0; keyTypeNext=1; keyTypeGid=4; (* KeyTypes for muGetUserInfo() only *) CONST keyTypeUserID=2; keyTypeUid=3; keyTypeGidNext=5; keyTypeUserName=6; (* Case-insensitive *) keyTypeWUserID=7; (* Case-insensitive, wild cards allowed *) keyTypeWUserName=8; (* Case-insensitive, wild cards allowed *) keyTypeWUserIDNext=9; keyTypeWUserNameNext=10; (* KeyTypes for muGetGroupInfo() only *) CONST keyTypeGroupID=11; (* Case-sensitive *) keyTypeWGroupID=12; (* Case-insensitive, wild cards allowed *) keyType_WGroupIDNext=13; keyTypeGroupName=14; (* Case-insensitive *) keyTypeWGroupName=15; (* Case-insensitive, wild cards allowed *) keyTypeWGroupNameNext=16; keyTypeMgrUid=17; keyTypeMgrUidNext=18; (* Extended Owner Information Structure A pointer to this structure is returned by muGetTaskExtOwner(). You MUST use muFreeExtOwner() to deallocate it!! *) TYPE ExtOwner=RECORD uid: CARDINAL; gid: CARDINAL; numSecGroups: CARDINAL; (* Number of Secondary Groups this *) (* user belongs too. *) END; (* NOTE: This structure is followed by a UWORD array containing *) (* the Secondary Group Numbers *) ExtOwnerPtr=POINTER TO ExtOwner; (* Portectionn bits *) (* Regular RWED bits are 0 == allowed. *) (* NOTE: GRP and OTR RWED permissions are 0 == not allowed! *) TYPE ProtectionFlags=( delete, (* prevent file from being deleted *) execute, (* ignored by system, used by Shell *) write, (* ignored by old filesystem *) read, (* ignored by old filesystem *) archive, (* cleared whenever file is changed *) pure, (* program is reentrant and rexecutable *) script, (* program is a script (execute) file *) grpDelete, (* Group: prevent file from being deleted *) grpExecute, (* Group: file is executable *) grpWrite, (* Group: file is writable *) grpRead, (* Group: file is readable *) otrDelete, (* Other: prevent file from being deleted *) otrExecute, (* Other: file is executable *) otrWrite, (* Other: file is writable *) otrRead, (* Other: file is readable *) pf16, pf17, pf18, pf19, pf20, pf21, pf22, pf23, pf24, pf25, pf26, pf27, pf28, pf29, pf30, setUid (* Change owner during execution *) ); ProtectionFlagSet=SET OF ProtectionFlags; (* Default Protection Bits *) CONST defprotection=ProtectionFlagSet{otrRead, grpRead}; (* Relations returned by muGetRelationshipA() *) TYPE Relations=( relbRootUid, (* User == super user *) relbRootGid, (* User belongs to the super user group *) relbNobody, (* User == nobody *) relbUidMatch, (* User == owner *) relbGidMatch, (* User belongs to owner group *) relbPrimGid, (* User's primary group == owner group *) relbNoOwner (* Owner == nobody *) ); RelationSet=SET OF Relations; (* Monitor Structure The use of this structure is restricted to root. Do not modify or reuse this structure while it is active! *) TYPE MonitorModes=(ignore, sendSignal, sendMessage); MonitorTriggers=( mtOwnerChange, (* Task Owner Change *) (* From: uid of old user *) (* To: uid of new user *) mtLogin, (* successful Login/Logout *) (* From: uid of old user *) (* To: uid of new user *) (* UserID: UserID of new user *) mtLoginFail, (* unsuccessful Login/Logout *) (* From: uid of old user *) (* UserID: UserID of new user *) mtPasswd, (* successful Passwd *) (* From: uid of user *) mtPasswdFail, (* unsuccessful Passwd *) (* From: uid of user *) mtCheckPasswd, (* successful CheckPasswd *) (* From: uid of user *) mtCheckPasswdFail (* unsuccessful CheckPasswd *) (* From: uid of user *) ); MonitorTriggerSet=SET OF MonitorTriggers; (* NOTE: This structure may be extended in future! *) Monitor=RECORD node: MinNode; mode: MonitorModes; triggers: MonitorTriggerSet; CASE :INTEGER OF | 0: task: TaskPtr; (* for SEND_SIGNAL *) signalNum: LONGCARD; | 1: port: MsgPortPtr; (* for SEND_MESSAGE *) END; END; MonitorPtr=POINTER TO Monitor; (* Monitor Message Sent to the application if SEND_MESSAGE is specified. Do NOT forget to reply! *) MonMsg=RECORD execMsg: Message; monitor: MonitorPtr; (* The monitor that sent the message *) trigger: MonitorTriggers; (* The trigger that caused the message *) from: CARDINAL; to: CARDINAL; userID: ARRAY [0..useridsize-1] OF CHAR; END; END MultiUserD.