/* Copyright 1998 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Lan Manager client * * Logon.C -- "Logon" interface to Omniclient * * This module produces a "Log on to Lan Manager" icon in the FS List * !Omni window, which lets the user log on (i.e. set a default * workgroup/domain, user name, and password). * * Versions * 29-05-96 INH Original, for LanMan 1.69 * 10-06-96 NAS Minor fixes for domain logon/OmniClient interface to work * 12-06-96 INH "Dismount" call deleted, OmniOp 17 made instead. * 25-07-96 INH Home directory stuff added */ #include <stdio.h> #include <string.h> #include <ctype.h> #include "kernel.h" #include "swis.h" #include "stdtypes.h" #include "lanman.h" #include "lmvars.h" #include "omni.h" #include "rpc.h" #include "logon.h" #include "xlate.h" #include "LanMan_MH.h" /* ----------------------------------- */ static void SetPassword ( char * pwd ) { static char pass_buf[NAME_LIMIT]; if ( pwd == NULL ) pwd = ""; strcpyn ( pass_buf, pwd, NAME_LIMIT ); Xlt_Jumble ( pass_buf ); LM_Vars.password_ptr = pass_buf; } /* ----------------------------------- */ static void SetOSVar ( char *varname, char *value ) { _kernel_swi_regs R; R.r[0] = (int) varname; R.r[1] = (int) value; if ( value == NULL ) /* Unset it */ R.r[2] = -1; else R.r[2] = strlen (value); R.r[3] = 0; R.r[4] = 4; /* Literal string */ _kernel_swi ( OS_SetVarVal, &R, &R ); } /* ----------------------------------- */ char Lgn_PrimaryDCName[NAME_LIMIT]; /* For debugging */ char Lgn_HomeServerName[NAME_LIMIT]; char Lgn_HomeShareName[NAME_LIMIT]; char Lgn_HomeDirName[DOS_NAME_LEN]; static bool get_path ( char **ptr_in_out, char *result ) { int i; char *p = *ptr_in_out; if (*p++ != '\\') return false; i=0; while ( *p != '\\' && *p != 0 ) { if ( i < NAME_LIMIT-1 ) result[i++] = *p; p++; } result[i] = 0; *ptr_in_out = p; return (bool) (i>0); } /* ----------------------------------- */ static err_t ParseHomeDir ( char *name ) { char *p; char leaf_name[NAME_LIMIT]; /* We expect the string to be of the form \\servername\sharename, with optionally a path on the end of it, which will be translated to RISCOS format. */ while ( isspace(*name) ) name++; /* Skip leading whitespace */ if ( name[0] != '\\' || name[1] != '\\' ) /* Doesn't start '\\' */ return EHOMEDIRNAME; name++; /* Make name \SERVER\SHARE[\path] */ if ( !get_path ( &name, Lgn_HomeServerName ) || !get_path ( &name, Lgn_HomeShareName ) ) return EHOMEDIRNAME; sprintf ( Lgn_HomeDirName, "%s::Home.$", FilingSystemName ); p = Lgn_HomeDirName + strlen(Lgn_HomeDirName); while ( get_path ( &name, leaf_name ) ) { *p++ = '.'; Xlt_NameDOStoRO ( p, leaf_name ); p += strlen(p); } return OK; } /* ----------------------------------- */ /* This function should check for CMOS default values, * * and use them if present - RCE 980122 * * Achieved by modifying its caller 980127:RCE * */ err_t Lgn_Init ( void ) { strcpy ( LM_Vars.workgroup, "WORKGROUP" ); strcpy ( LM_Vars.username, "GUEST" ); SetPassword ( NULL ); LM_Vars.logged_on = true; return OK; } /* ----------------------------------- */ err_t Lgn_Logon ( char *wkgrp, char *userid, char *pwd ) { char *serv_name; char *dir_name; int tmp; err_t res; if ( userid == NULL || userid[0] == 0 ) return EUSERUNKNOWN; if ( wkgrp != NULL && strlen(wkgrp) > 0 ) strcpyn_upper ( LM_Vars.workgroup, wkgrp, NAME_LIMIT ); /* pwd may be NULL */ strcpyn ( LM_Vars.username, userid, NAME_LIMIT ); SetPassword ( pwd ); LM_Vars.logged_on = true; SetOSVar("Omni$UserLanMan", LM_Vars.username); SetOSVar("LanMan$HomeDir", NULL ); Lgn_HomeDirName[0] = 0; Omni_RecheckInfo (RI_MOUNTS); Omni_RecheckInfo (RI_SERVERS); Omni_RecheckInfo (RI_PRINTERS); /* Now attempt to find home directory */ serv_name = RPC_GetDomainController ( LM_Vars.workgroup ); if ( serv_name == NULL ) /* No DC: Don't worry about it */ { strcpy ( Lgn_PrimaryDCName, "<not found>"); return OK; } strcpy ( Lgn_PrimaryDCName, serv_name ); /* Report bad passwords & other errors, ignore unset home directories */ res = RPC_LogonUser ( serv_name, LM_Vars.username, pwd, &dir_name ); if ( res == ENOTPRESENT ) /* Server doesn't support it */ return OK; if ( res != OK ) return res; /* Extract fields from name, & try to connect to it */ if ( dir_name == NULL || dir_name[0] == 0 ) return OK; res = ParseHomeDir ( dir_name ); if ( res != OK ) return res; /* Set the home directory name so it is available to the boot file */ SetOSVar ( "LanMan$HomeDir", Lgn_HomeDirName ); res = Omni_MountServer ( Lgn_HomeServerName, LM_Vars.username, pwd, "Home", /* Mountname */ Lgn_HomeShareName, &tmp ); /* MountID_out */ /* Caution - this could potentially recurse, as the !ARMBOOT file may contain an LMLogon command! */ if ( res == OK || res == ECONNEXISTS ) return OK; else return EHOMEDIRCONN; } /* ----------------------------------- */ err_t Lgn_Logoff ( void ) { strcpy ( LM_Vars.username, "" ); SetPassword(NULL); LM_Vars.logged_on = false; Omni_ClearLists(); SetOSVar ( "Omni$UserLanMan", NULL ); SetOSVar ( "LanMan$HomeDir", NULL ); Omni_RecheckInfo ( RI_SERVERS ); return OK; } /* --------------------------------------- */ void Lgn_Register(void) { (void) _swix( SWI_Omni_RegisterClient, _INR(0,6), LanMan_LogonOp, /* Client ID */ RC_LOGON_TYPE | RC_NEEDS_AUTHSERV | RC_NEEDS_USERID | RC_NEEDS_PASSWD, "lmlgni", "LAN Manager", /* Needs to be reasonably short. NAS */ "LanManFS Logon bit", /* Info string - shouldn't appear*/ 0, /* Site ID */ "LanMan+"); /* Needs to be unique from LanMan FS name. NAS */ } /* ---------------------------------------- */ static err_t Lgn_ListServers ( char *buf_ptr, int buf_size, int token_in, char * *pNextByte_out, int *pToken_out ) { char *shortname = "LanManager"; /* Needs to be reasonably short. NAS */ char *longname = "LanManager"; /* Needs to be reasonably short. NAS */ char *extradetails = "Logon Network\n \n "; int serverid = (int) "?"; /* A unique memory address */ int tot_size; tot_size = sizeof ( serverid ) + strlen(shortname) + 1 + strlen (longname ) + 1 + strlen (extradetails) + 1; tot_size = (tot_size + 3) & ~3; /* Round to dword boundary */ /* We only ever write one record */ if ( token_in != 0 || tot_size > buf_size ) { *pNextByte_out = buf_ptr; /* No records written */ *pToken_out = 0; /* All done */ return OK; } *pNextByte_out = buf_ptr + tot_size; *pToken_out = 0; memcpy ( buf_ptr, &serverid, sizeof(serverid) ); buf_ptr += sizeof(serverid); strcpy ( buf_ptr, shortname ); buf_ptr += strlen(shortname)+1; strcpy ( buf_ptr, longname ); buf_ptr += strlen(longname)+1; strcpy ( buf_ptr, extradetails ); return OK; } /* ---------------------------------------- */ _kernel_oserror *Lgn_LogonOp_SWI ( _kernel_swi_regs *R ) { err_t res; debug1(" Omni Op(%d):", R->r[0]); #define Rin_int(a) (R->r[a]) #define Rout_int(a) &(R->r[a]) #define Rin_chr(a) (char *)(R->r[a]) #define Rout_chr(a) (char **)&(R->r[a]) switch ( R->r[0] ) { case 0: /* Mount */ res = Lgn_Logon ( Rin_chr(1), /* "Server" => domain/workgroup */ Rin_chr(2), /* User ID */ Rin_chr(3) ); /* Password */ if ( res == OK || res == EHOMEDIRCONN || res == EHOMEDIRNAME) R->r[1] = 1; /* Keep the Smith happy */ else R->r[1] = 0; /* NAS 05/Dec/96: needs to return mount_id of 0 if error */ break; case 3: /* Enumerate servers */ res = Lgn_ListServers ( Rin_chr(1), Rin_int(2), Rin_int(3), Rout_chr(1), Rout_int(3) ); break; case 9: /* Get mount info - (mild bodge - say it's not there!) */ R->r[3] = 0; res = OK; break; case 17: /* Log out of domain */ res = Lgn_Logoff(); /* Clear all user ID's & passwords */ break; default: res = ENOTPRESENT; } return Xlt_Error(res); }