From d03840f85c698a39483b225133898a36d57dce2e Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 11 Jul 2004 22:22:57 +0000 Subject: [PATCH 1/1] smb-auth-20040711 Over last several years significant efforts have been made to work around the inability to protect user tokens from use by inappropriate entities. The tokens are associated with a given userid and session by a combination of an SMB based ioctl and an authenticated/encrypted RPC. This has opened the door for tokens to be borrowed by other users if they could connect to the same SMB server with the identical userid. This was trivially possible because the SMB connections were unauthenticated. This patch adds two forms of authenticated SMB connections: NTLM and Extended Security (aka GSS SPNEGO). By default Extended Security mode is used. This patch has been tested on 2000 workstation, 2000 server, XP SP1, and 2003 Server, and XP SP2 RC2. The Extended Security works on all platforms except for XP SP2 RC2 regards of whether or not the machine is part of a domain or not; and whether or not a local or domain account is used. On XP SP2 RC2, attempts to use negotiate Extended Security result in a Logon Denied error from AcceptSecurityContext() and a substatus code of 0x7C90486A is logged to the Security Event log via the NTLM SSP. The SMB AUTH NTLM mode succeeds on XP SP2 RC2. Disabling SMB Authentication or specifying the use of NTLM mode may be done via the registry. Value : smbAuthType Type : DWORD {0..2} Default : 2 If this value is specified, it defines the type of SMB authentication which must be present in order for the Windows SMB client to connect to the AFS Client Service's SMB server. The values are: 0 = No authentication required 1 = NTLM authentication required 2 = Extended (GSS SPNEGO) authentication required The default is Extended authentication --- doc/txt/winnotes/afs-install-notes.txt | 41 +- doc/txt/winnotes/registry.txt | 17 + src/WINNT/afsd/afsd_init.c | 10 + src/WINNT/afsd/afskfw.c | 12 +- src/WINNT/afsd/cm.h | 4 +- src/WINNT/afsd/smb.c | 271 ++++++++++-- src/WINNT/afsd/smb.h | 93 +++- src/WINNT/afsd/smb3.c | 755 +++++++++++++++++++++++++++++++-- src/WINNT/afsd/smb3.h | 3 + src/WINNT/install/NSIS/AFSCell.ini | 26 +- src/WINNT/install/NSIS/OpenAFS.nsi | 50 ++- src/config/NTMakefile.i386_nt40 | 2 +- src/rxkad/rxkad.p.h | 8 +- 13 files changed, 1177 insertions(+), 115 deletions(-) diff --git a/doc/txt/winnotes/afs-install-notes.txt b/doc/txt/winnotes/afs-install-notes.txt index d3f0871..4fdf39a 100644 --- a/doc/txt/winnotes/afs-install-notes.txt +++ b/doc/txt/winnotes/afs-install-notes.txt @@ -69,9 +69,9 @@ automatically result in a new read-only mount point being created in the fake root.afs volume. These mount points are preserved between service starts in the %WINDIR%\afs_freelance.ini file. -Unfortunately, at the current time it is not possible to create read-write -mount points in the fake root.afs cell. This is a limitation which will be -addressed in a future release. +As of 1.3.66, Freelance mode supports read-write mount points in the fake +root.afs volume. In addition, if the mount point list is empty, mount points +for "cellname" (ro) and ".cellname" (rw) will be automatically generated. 4. The OpenAFS for Windows client will make use of AFSDB DNS records to discover cell information when it is not located in the local CellServDB file @@ -103,7 +103,9 @@ In particular, if you are using this mode it is crucial that new AFS tokens not be obtained after the logon session starts except via the AFS Systray tool as started by the AFS Network Provider. If the AFS Systray tool is stopped you must log off to obtain new tokens. Do not use external tools such as -"aklog.exe" if High Security mode is turned on. +"aklog.exe" if High Security mode is turned on. As of 1.3.66, OpenAFS supports +Authenticated SMB connections which removes the need for High Security mode. +DO NOT USE IT!!!!! 7. The AFS Systray tool (afscreds.exe) supports several new command line options: @@ -178,11 +180,15 @@ reports. 13. OpenAFS for Windows does not support files larger than 2GB. 14. There are documented problems running the AFS Client on Hyperthreaded -Pentium 4 machines. At the current time it is recommended that hyper- -threading be disabled in the machine configuration. +Pentium 4 machines. As of 1.3.66, a registry entry may be created to specify +that the AFS Client Service should only use a single processor. If you have +a hyperthreaded system it is strongly advised that this registry value be set. +See "registry.txt" for details on the MaxCPUs value. 15. OpenAFS for Windows currently requires the use of TCP based RPC. If the machine is restricted to Local RPC only, you will be unable to store tokens. +As of 1.3.66, Local RPC is used as the default RPC mechanism for setting +tokens. TCP RPC is still used for debugging and other functions. 16. OpenAFS for Windows does not automatically open ports in the Windows Internet Connection Firewall. You must manually open port 7001 to allow for @@ -192,6 +198,29 @@ incoming callback messages to be received by AFS file servers. encrypted data transfer between the AFS client and the AFS servers. This is often referred to as "crypt" mode. +18. OpenAFS 1.3.66 adds support for authenticated SMB connections using +either NTLM or GSS SPNEGO (NTLM, Kerberos 5, ...). In previous versions +of OpenAFS the SMB connections were unauthenticated which left open the +door for several security holes which could be used to obtain access to +the use of other user's tokens on shared machines. With the introduction +of authenticated SMB connections the so called High Security mode should +no longer be used. + +When GSS SPNEGO results in a Kerberos 5 authentication, the Windows SMB +client will attempt to retrieve service tickets for "cifs/afs@REALM" (if +the loopback adapter is in use) or "cifs/machine-afs@REALM" (if the loopback +adapter is not being used). It is extremely important that this service +principal not exist in the KDC database. If the request for this ticket +fails, a subsequent request for "cifs/HOST$@REALM" will be issued. This +service principal should exist in the KDC database. The key associated +with this service principal must match the key assigned to +"host/machine@REALM". If the local machine is part of a Windows Domain +this will all be taken care of for you. If the local machine is using +a non-MS KDC for authentication, then your KDC administrator will have to +add these service principals to the list of principals to be maintained +for each host. + + ------------------------------------------------------------------------ Reporting Bugs: diff --git a/doc/txt/winnotes/registry.txt b/doc/txt/winnotes/registry.txt index ee1ede4..124094a 100644 --- a/doc/txt/winnotes/registry.txt +++ b/doc/txt/winnotes/registry.txt @@ -291,6 +291,17 @@ Default : NOTE: Setting this entry to "1" may be required on hyperthreaded systems to avoid crashes in the RX library. +Value : smbAuthType +Type : DWORD {0..2} +Default : 2 + + If this value is specified, it defines the type of SMB authentication + which must be present in order for the Windows SMB client to connect + to the AFS Client Service's SMB server. The values are: + 0 = No authentication required + 1 = NTLM authentication required + 2 = Extended (GSS SPNEGO) authentication required + The default is Extended authentication Regkey: [HKLM\SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters\GlobalAutoMapper] @@ -388,6 +399,12 @@ NSIS : \afslogon.dll Specifies the DLL to use for the network provider +Value : TraceOption +Type : DWORD {1|0} +Default : 0 + + Enables trace events for the network provider. + Value : VerboseLogging Type : DWORD NSIS : 0x0a diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index e7bc28a..f88f590 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -550,6 +550,16 @@ int afsd_InitCM(char **reasonP) } afsi_log("Maximum number of VCs per server is %d", smb_maxVCPerServer); + dummyLen = sizeof(smb_authType); + code = RegQueryValueEx(parmKey, "SMBAuthType", NULL, NULL, + (BYTE *) &smb_authType, &dummyLen); + + if (code != ERROR_SUCCESS || + (smb_authType != SMB_AUTH_EXTENDED && smb_authType != SMB_AUTH_NTLM && smb_authType != SMB_AUTH_NONE)) { + smb_authType = SMB_AUTH_EXTENDED; /* default is to use extended authentication */ + } + afsi_log("SMB authentication type is %s", ((smb_authType == SMB_AUTH_NONE)?"NONE":((smb_authType == SMB_AUTH_EXTENDED)?"EXTENDED":"NTLM"))); + dummyLen = sizeof(rx_nojumbo); code = RegQueryValueEx(parmKey, "RxNoJumbo", NULL, NULL, (BYTE *) &rx_nojumbo, &dummyLen); diff --git a/src/WINNT/afsd/afskfw.c b/src/WINNT/afsd/afskfw.c index bf489b6..fbf1056 100644 --- a/src/WINNT/afsd/afskfw.c +++ b/src/WINNT/afsd/afskfw.c @@ -2718,13 +2718,13 @@ KFW_AFS_klog( } if ( smbname ) { - strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN); - aclient.smbname[MAXRANDOMNAMELEN-1] = '\0'; + strncpy(aclient.smbname, smbname, sizeof(aclient.smbname)); + aclient.smbname[sizeof(aclient.smbname)-1] = '\0'; } else { aclient.smbname[0] = '\0'; } - rc = ktc_SetToken(&aserver, &atoken, &aclient, 0); + rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)); if (!rc) goto cleanup; /* We have successfully inserted the token */ @@ -2836,13 +2836,13 @@ KFW_AFS_klog( strcpy(aclient.cell, CellName); if ( smbname ) { - strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN); - aclient.smbname[MAXRANDOMNAMELEN-1] = '\0'; + strncpy(aclient.smbname, smbname, sizeof(aclient.smbname)); + aclient.smbname[sizeof(aclient.smbname)-1] = '\0'; } else { aclient.smbname[0] = '\0'; } - if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0)) + if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0))) { KFW_AFS_error(rc, "ktc_SetToken()"); code = rc; diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index 62fa7f8..8f3d53a 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -219,7 +219,7 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_EXISTS (CM_ERROR_BASE+11) #define CM_ERROR_CROSSDEVLINK (CM_ERROR_BASE+12) #define CM_ERROR_BADOP (CM_ERROR_BASE+13) -/* CM_ERROR_BADPASSWORD used to be here */ +#define CM_ERROR_BADPASSWORD (CM_ERROR_BASE+14) #define CM_ERROR_NOTDIR (CM_ERROR_BASE+15) #define CM_ERROR_ISDIR (CM_ERROR_BASE+16) #define CM_ERROR_READONLY (CM_ERROR_BASE+17) @@ -246,4 +246,6 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_RENAME_IDENTICAL (CM_ERROR_BASE+39) #define CM_ERROR_ALLOFFLINE (CM_ERROR_BASE+40) #define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) +#define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) +#define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) #endif /* __CM_H_ENV__ */ diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 46df33e..10e69c5 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -28,6 +28,7 @@ #include #include +#include #include "afsd.h" @@ -87,6 +88,11 @@ int numNCBs, numSessions, numVCs; int smb_maxVCPerServer; int smb_maxMpxRequests; +int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */ +HANDLE smb_lsaHandle; +ULONG smb_lsaSecPackage; +LSA_STRING smb_lsaLogonOrigin; + #define NCBmax MAXIMUM_WAIT_OBJECTS EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax]; EVENT_HANDLE **NCBreturns; @@ -187,6 +193,15 @@ extern char cm_confDir[]; extern char AFSConfigKeyName[]; +char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */ +int smb_ServerDomainNameLength = 0; +char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */ +int smb_ServerOSLength = sizeof(smb_ServerOS); +char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */ +int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager); + +GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }}; + /* * Demo expiration * @@ -738,6 +753,33 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana) lock_InitializeMutex(&vcp->mx, "vc_t mutex"); vcp->lsn = lsn; vcp->lana = lana; + vcp->secCtx = NULL; + + if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) { + /* We must obtain a challenge for extended auth + * in case the client negotiates smb v3 + */ + NTSTATUS nts,ntsEx; + MSV1_0_LM20_CHALLENGE_REQUEST lsaReq; + PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp; + ULONG lsaRespSize; + + lsaReq.MessageType = MsV1_0Lm20ChallengeRequest; + + nts = LsaCallAuthenticationPackage( smb_lsaHandle, + smb_lsaSecPackage, + &lsaReq, + sizeof(lsaReq), + &lsaResp, + &lsaRespSize, + &ntsEx); + osi_assert(nts == STATUS_SUCCESS); /* this had better work! */ + + memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH); + LsaFreeReturnBuffer(lsaResp); + } + else + memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH); } lock_ReleaseWrite(&smb_rctLock); return vcp; @@ -2097,6 +2139,15 @@ void smb_MapNTError(long code, unsigned long *NTStatusp) else if (code == CM_ERROR_AMBIGUOUS_FILENAME) { NTStatus = 0xC0000035L; /* Object name collision */ } + else if (code == CM_ERROR_BADPASSWORD) { + NTStatus = 0xC000006DL; /* unknown username or bad password */ + } + else if (code == CM_ERROR_BADLOGONTYPE) { + NTStatus = 0xC000015BL; /* logon type not granted */ + } + else if (code == CM_ERROR_GSSCONTINUE) { + NTStatus = 0xC0000016L; /* more processing required */ + } else { NTStatus = 0xC0982001L; /* SMB non-specific error */ } @@ -2248,6 +2299,11 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep, class = 1; error = 183; /* Samba uses this */ } + else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) { + /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */ + class = 2; + error = 2; /* bad password */ + } else { class = 2; error = 1; @@ -2423,18 +2479,22 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *namep; + char *datap; int coreProtoIndex; int v3ProtoIndex; int NTProtoIndex; - int protoIndex; /* index we're using */ + int protoIndex; /* index we're using */ int namex; int dbytes; int entryLength; int tcounter; - char protocol_array[10][1024]; /* protocol signature of the client */ + char protocol_array[10][1024]; /* protocol signature of the client */ + int caps; /* capabilities */ + time_t unixTime; + long dosTime; + TIME_ZONE_INFORMATION tzi; - - osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops", + osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops", ongoingOps - 1); if (!isGateway) { if (active_vcp) { @@ -2545,12 +2605,23 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (protoIndex == -1) return CM_ERROR_INVAL; else if (NTProtoIndex != -1) { - smb_SetSMBParm(outp, 0, protoIndex); - smb_SetSMBParmByte(outp, 1, 0); /* share level security, no passwd encrypt */ + smb_SetSMBParm(outp, 0, protoIndex); + if (smb_authType != SMB_AUTH_NONE) { + smb_SetSMBParmByte(outp, 1, + NEGOTIATE_SECURITY_USER_LEVEL | + NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */ + } else { + smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */ + } smb_SetSMBParm(outp, 1, smb_maxMpxRequests); /* max multiplexed requests */ smb_SetSMBParm(outp, 2, smb_maxVCPerServer); /* max VCs per consumer/server connection */ - smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */ - smb_SetSMBParmLong(outp, 5, 65536); /* raw buffer size */ + smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */ + smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE); /* raw buffer size */ + /* The session key is not a well documented field however most clients + * will echo back the session key to the server. Currently we are using + * the same value for all sessions. We should generate a random value + * and store it into the vcp + */ smb_SetSMBParm(outp, 7, 1); /* next 2: session key */ smb_SetSMBParm(outp, 8, 1); /* @@ -2568,30 +2639,100 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * and NT Find * * and NT SMB's * * and raw mode */ - smb_SetSMBParmLong(outp, 9, 0x251); - smb_SetSMBParmLong(outp, 11, 0);/* XXX server time: do we need? */ - smb_SetSMBParmLong(outp, 13, 0);/* XXX server date: do we need? */ - smb_SetSMBParm(outp, 15, 0); /* XXX server tzone: do we need? */ - smb_SetSMBParmByte(outp, 16, 0);/* Encryption key length */ - smb_SetSMBDataLength(outp, 0); /* perhaps should specify 8 bytes anyway */ + caps = NTNEGOTIATE_CAPABILITY_NTSTATUS | + NTNEGOTIATE_CAPABILITY_NTFIND | + NTNEGOTIATE_CAPABILITY_RAWMODE | + NTNEGOTIATE_CAPABILITY_NTSMB; + + if ( smb_authType == SMB_AUTH_EXTENDED ) + caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY; + + smb_SetSMBParmLong(outp, 9, caps); + time(&unixTime); + smb_SearchTimeFromUnixTime(&dosTime, unixTime); + smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */ + smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */ + + GetTimeZoneInformation(&tzi); + smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias); /* server tzone */ + + if (smb_authType == SMB_AUTH_NTLM) { + smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */ + smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength); + /* paste in encryption key */ + datap = smb_GetSMBData(outp, NULL); + memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH); + /* and the faux domain name */ + strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName); + } else if ( smb_authType == SMB_AUTH_EXTENDED ) { + void * secBlob; + int secBlobLength; + + smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */ + + smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength); + + smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID)); + + datap = smb_GetSMBData(outp, NULL); + memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID)); + + if (secBlob) { + datap += sizeof(smb_ServerGUID); + memcpy(datap, secBlob, secBlobLength); + free(secBlob); + } + } else { + smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */ + smb_SetSMBDataLength(outp, 0); /* Perhaps we should specify 8 bytes anyway */ + } } else if (v3ProtoIndex != -1) { smb_SetSMBParm(outp, 0, protoIndex); - smb_SetSMBParm(outp, 1, 0); /* share level security, no passwd encrypt */ + + /* NOTE: Extended authentication cannot be negotiated with v3 + * therefore we fail over to NTLM + */ + if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) { + smb_SetSMBParm(outp, 1, + NEGOTIATE_SECURITY_USER_LEVEL | + NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */ + } else { + smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */ + } smb_SetSMBParm(outp, 2, SMB_PACKETSIZE); smb_SetSMBParm(outp, 3, smb_maxMpxRequests); /* max multiplexed requests */ smb_SetSMBParm(outp, 4, smb_maxVCPerServer); /* max VCs per consumer/server connection */ smb_SetSMBParm(outp, 5, 0); /* no support of block mode for read or write */ smb_SetSMBParm(outp, 6, 1); /* next 2: session key */ smb_SetSMBParm(outp, 7, 1); - smb_SetSMBParm(outp, 8, 0); /* XXX server time: do we need? */ - smb_SetSMBParm(outp, 9, 0); /* XXX server date: do we need? */ - smb_SetSMBParm(outp, 10, 0); /* XXX server tzone: do we need? */ - smb_SetSMBParm(outp, 11, 0); /* resvd */ - smb_SetSMBParm(outp, 12, 0); /* resvd */ - smb_SetSMBDataLength(outp, 0); /* perhaps should specify 8 bytes anyway */ + time(&unixTime); + smb_SearchTimeFromUnixTime(&dosTime, unixTime); + smb_SetSMBParm(outp, 8, LOWORD(dosTime)); /* server time */ + smb_SetSMBParm(outp, 9, HIWORD(dosTime)); /* server date */ + + GetTimeZoneInformation(&tzi); + smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias); /* server tzone */ + + /* NOTE: Extended authentication cannot be negotiated with v3 + * therefore we fail over to NTLM + */ + if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) { + smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH); /* encryption key length */ + smb_SetSMBParm(outp, 12, 0); /* resvd */ + smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength); /* perhaps should specify 8 bytes anyway */ + datap = smb_GetSMBData(outp, NULL); + /* paste in a new encryption key */ + memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH); + /* and the faux domain name */ + strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName); + } else { + smb_SetSMBParm(outp, 11, 0); /* encryption key length */ + smb_SetSMBParm(outp, 12, 0); /* resvd */ + smb_SetSMBDataLength(outp, 0); + } } - else if (coreProtoIndex != -1) { + else if (coreProtoIndex != -1) { /* not really supported anymore */ smb_SetSMBParm(outp, 0, protoIndex); smb_SetSMBDataLength(outp, 0); } @@ -2605,8 +2746,21 @@ void smb_Daemon(void *parmp) while(1) { count++; thrd_Sleep(10000); - if ((count % 360) == 0) /* every hour */ - smb_CalculateNowTZ(); + if ((count % 360) == 0) { /* every hour */ + struct tm myTime; + + /* Initialize smb_localZero */ + myTime.tm_isdst = -1; /* compute whether on DST or not */ + myTime.tm_year = 70; + myTime.tm_mon = 0; + myTime.tm_mday = 1; + myTime.tm_hour = 0; + myTime.tm_min = 0; + myTime.tm_sec = 0; + smb_localZero = mktime(&myTime); + + smb_CalculateNowTZ(); + } /* XXX GC dir search entries */ } } @@ -5822,9 +5976,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, outWctp = outp->wctp; smbp = (smb_t *) &outp->data; if (code != CM_ERROR_PARTIALWRITE - && code != CM_ERROR_BUFFERTOOSMALL) { + && code != CM_ERROR_BUFFERTOOSMALL + && code != CM_ERROR_GSSCONTINUE) { /* nuke wct and bcc. For a partial - * write, assume they're OK. + * write or an in-process authentication handshake, + * assume they're OK. */ *outWctp++ = 0; *outWctp++ = 0; @@ -7140,6 +7296,69 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, smb3_Init(); + /* if we are doing SMB authentication we have register outselves as a logon process */ + if (smb_authType != SMB_AUTH_NONE) { + NTSTATUS nts; + LSA_STRING afsProcessName; + LSA_OPERATIONAL_MODE dummy; /*junk*/ + DWORD bufsize; + + afsProcessName.Buffer = "OpenAFSClientDaemon"; + afsProcessName.Length = strlen(afsProcessName.Buffer); + afsProcessName.MaximumLength = afsProcessName.Length + 1; + + nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy); + + if (nts == STATUS_SUCCESS) { + LSA_STRING packageName; + /* we are registered. Find out the security package id */ + packageName.Buffer = MSV1_0_PACKAGE_NAME; + packageName.Length = strlen(packageName.Buffer); + packageName.MaximumLength = packageName.Length + 1; + nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage); + if (nts == STATUS_SUCCESS) { + /* Now get ourselves a domain name. */ + /* For now we are using the local computer name as the domain name. + * It is actually the domain for local logins, and we are acting as + * a local SMB server. + */ + bufsize = sizeof(smb_ServerDomainName) - 1; + GetComputerName(smb_ServerDomainName, &bufsize); + smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */ + afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName); + + smb_lsaLogonOrigin.Buffer = "OpenAFS"; + smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer); + smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1; + } else { + afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts); + } + } else { + afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts); + } + + if (nts != STATUS_SUCCESS) { + /* something went wrong. We report the error and revert back to no authentication + because we can't perform any auth requests without a successful lsa handle + or sec package id. */ + afsi_log("Reverting to NO SMB AUTH"); + smb_authType = SMB_AUTH_NONE; + } else if ( smb_authType == SMB_AUTH_EXTENDED) { + /* Test to see if there is anything to negotiate. If SPNEGO is not going to be used + * then the only option is NTLMSSP anyway; so just fallback. + */ + void * secBlob; + int secBlobLength; + + smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength); + if (secBlobLength == 0) { + smb_authType = SMB_AUTH_NTLM; + afsi_log("Reverting to SMB AUTH NTLM"); + } else + free(secBlob); + } + } + /* Start listeners, waiters, servers, and daemons */ for (i = 0; i < lana_list.length; i++) { diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 6396ad0..1740149 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -14,6 +14,8 @@ #include "netbios95.h" #endif /* DJGPP */ +#include + /* basic core protocol SMB structure */ typedef struct smb { unsigned char id[4]; @@ -43,7 +45,35 @@ typedef struct smb { #define SMB_FLAG_CREATE 1 /* create the structure if necessary */ /* max # of bytes we'll receive in an incoming SMB message */ -#define SMB_PACKETSIZE 8400 +/* the maximum is 2^18-1 for NBT and 2^25-1 for Raw transport messages */ +/* we will use something smaller but large enough to be efficient */ +#define SMB_PACKETSIZE 32768 /* was 8400 */ +/* raw mode is considered obsolete and cannot be used with message signing */ +#define SMB_MAXRAWSIZE 65536 + +/* Negotiate protocol constants */ +/* Security */ +#define NEGOTIATE_SECURITY_USER_LEVEL 0x01 +#define NEGOTIATE_SECURITY_CHALLENGE_RESPONSE 0x02 +#define NEGOTIATE_SECURITY_SIGNATURES_ENABLED 0x04 +#define NEGOTIATE_SECURITY_SIGNATURES_REQUIRED 0x08 + +/* Capabilities */ +#define NTNEGOTIATE_CAPABILITY_RAWMODE 0x00000001L +#define NTNEGOTIATE_CAPABILITY_MPXMODE 0x00000002L +#define NTNEGOTIATE_CAPABILITY_UNICODE 0x00000004L +#define NTNEGOTIATE_CAPABILITY_LARGEFILES 0x00000008L +#define NTNEGOTIATE_CAPABILITY_NTSMB 0x00000010L +#define NTNEGOTIATE_CAPABILITY_RPCAPI 0x00000020L +#define NTNEGOTIATE_CAPABILITY_NTSTATUS 0x00000040L +#define NTNEGOTIATE_CAPABILITY_LEVEL_II_OPLOCKS 0x00000080L +#define NTNEGOTIATE_CAPABILITY_LOCK_AND_READ 0x00000100L +#define NTNEGOTIATE_CAPABILITY_NTFIND 0x00000200L +#define NTNEGOTIATE_CAPABILITY_DFS 0x00001000L +#define NTNEGOTIATE_CAPABILITY_NT_INFO_PASSTHRU 0x00002000L +#define NTNEGOTIATE_CAPABILITY_BULK_TRANSFER 0x20000000L +#define NTNEGOTIATE_CAPABILITY_COMPRESSED 0x40000000L +#define NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY 0x80000000L /* a packet structure for receiving SMB messages; locked by smb_globalLock. * Most of the work involved is in handling chained requests and responses. @@ -111,23 +141,27 @@ typedef struct myncb { /* one per virtual circuit */ typedef struct smb_vc { struct smb_vc *nextp; /* not used */ - int refCount; /* the reference count */ - long flags; /* the flags, if any; locked by mx */ - osi_mutex_t mx; /* the mutex */ + int refCount; /* the reference count */ + long flags; /* the flags, if any; locked by mx */ + osi_mutex_t mx; /* the mutex */ long vcID; /* VC id */ - unsigned short lsn; /* the NCB LSN associated with this */ + unsigned short lsn; /* the NCB LSN associated with this */ unsigned short uidCounter; /* session ID counter */ - unsigned short tidCounter; /* tree ID counter */ - unsigned short fidCounter; /* file handle ID counter */ - struct smb_tid *tidsp; /* the first child in the tid list */ - struct smb_user *usersp; /* the first child in the user session list */ - struct smb_fid *fidsp; /* the first child in the open file list */ + unsigned short tidCounter; /* tree ID counter */ + unsigned short fidCounter; /* file handle ID counter */ + struct smb_tid *tidsp; /* the first child in the tid list */ + struct smb_user *usersp; /* the first child in the user session list */ + struct smb_fid *fidsp; /* the first child in the open file list */ struct smb_user *justLoggedOut; /* ready for profile upload? */ unsigned long logoffTime; /* tick count when logged off */ /*struct cm_user *logonDLLUser; /* integrated logon user */ unsigned char errorCount; - char rname[17]; + char rname[17]; int lana; + char encKey[MSV1_0_CHALLENGE_LENGTH]; /* MSV1_0_CHALLENGE_LENGTH is 8 */ + void * secCtx; /* security context when negotiating SMB extended auth + * valid when SMB_VCFLAG_AUTH_IN_PROGRESS is set + */ } smb_vc_t; /* have we negotiated ... */ @@ -137,6 +171,8 @@ typedef struct smb_vc { #define SMB_VCFLAG_STATUS32 8 /* use 32-bit NT status codes */ #define SMB_VCFLAG_REMOTECONN 0x10 /* bad: remote conns not allowed */ #define SMB_VCFLAG_ALREADYDEAD 0x20 /* do not get tokens from this vc */ +#define SMB_VCFLAG_SESSX_RCVD 0x40 /* we received at least one session setups on this vc */ +#define SMB_VCFLAG_AUTH_IN_PROGRESS 0x80 /* a SMB NT extended authentication is in progress */ /* one per user session */ typedef struct smb_user { @@ -161,6 +197,8 @@ typedef struct smb_username { #define SMB_USERFLAG_DELETE 1 /* delete struct when ref count zero */ +#define SMB_MAX_USERNAME_LENGTH 256 + /* one per tree-connect */ typedef struct smb_tid { struct smb_tid *nextp; /* next sibling */ @@ -453,6 +491,39 @@ extern int smb_maxMpxRequests; /* max # of mpx requests */ extern int smb_hideDotFiles; extern unsigned int smb_IsDotFile(char *lastComp); +/* the following are used for smb auth */ +extern int smb_authType; /* Type of SMB authentication to be used. One from below. */ + +#define SMB_AUTH_NONE 0 +#define SMB_AUTH_NTLM 1 +#define SMB_AUTH_EXTENDED 2 + +extern HANDLE smb_lsaHandle; /* LSA handle obtained during smb_init if using SMB auth */ +extern ULONG smb_lsaSecPackage; /* LSA security package id. Set during smb_init */ +extern char smb_ServerDomainName[]; +extern int smb_ServerDomainNameLength; +extern char smb_ServerOS[]; +extern int smb_ServerOSLength; +extern char smb_ServerLanManager[]; +extern int smb_ServerLanManagerLength; +extern GUID smb_ServerGUID; +extern LSA_STRING smb_lsaLogonOrigin; + +/* used for getting a challenge for SMB auth */ +typedef struct _MSV1_0_LM20_CHALLENGE_REQUEST { + MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType; +} MSV1_0_LM20_CHALLENGE_REQUEST, *PMSV1_0_LM20_CHALLENGE_REQUEST; + +typedef struct _MSV1_0_LM20_CHALLENGE_RESPONSE { + MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType; + UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH]; +} MSV1_0_LM20_CHALLENGE_RESPONSE, *PMSV1_0_LM20_CHALLENGE_RESPONSE; +/**/ + +extern long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength); + +extern long smb_GetNormalizedUsername(char * usern, const char * accountName, const char * domainName); + extern void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 8d3669e..c2f8451 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -12,6 +12,8 @@ #ifndef DJGPP #include +#define SECURITY_WIN32 +#include #endif /* !DJGPP */ #include #include @@ -106,35 +108,687 @@ unsigned char *smb_ParseString(unsigned char *inp, char **chainpp) return inp; } +/*DEBUG do not checkin*/ +void OutputDebugF(char * format, ...) { +#ifdef COMMENT + va_list args; + int len; + char * buffer; + + va_start( args, format ); + len = _vscprintf( format, args ) // _vscprintf doesn't count + + 3; // terminating '\0' + '\n' + buffer = malloc( len * sizeof(char) ); + vsprintf( buffer, format, args ); + strcat(buffer, "\n"); + OutputDebugString(buffer); + free( buffer ); +#endif +} + +void OutputDebugHexDump(unsigned char * buffer, int len) { +#ifdef COMMENT + int i,j,k; + char buf[256]; + static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + OutputDebugF("Hexdump length [%d]",len); + + for(i=0;i7)?1:0); + k = buffer[i]; + + buf[j] = tr[k / 16]; buf[j+1] = tr[k % 16]; + + j = (i%16); + j = j + 56 + ((j>7)?1:0); + + buf[j] = (k>32 && k<127)?k:'.'; + } + if(i) + OutputDebugString(buf); +#endif +} +/**/ + +#define SMB_EXT_SEC_PACKAGE_NAME "Negotiate" +void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength){ + SECURITY_STATUS status, istatus; + CredHandle creds; + TimeStamp expiry; + SecBufferDesc secOut; + SecBuffer secTok; + CtxtHandle ctx; + ULONG flags; + + *secBlob = NULL; + *secBlobLength = 0; + + OutputDebugF("Negotiating Extended Security"); + + status = AcquireCredentialsHandle( + NULL, + SMB_EXT_SEC_PACKAGE_NAME, + SECPKG_CRED_INBOUND, + NULL, + NULL, + NULL, + NULL, + &creds, + &expiry); + + if (status != SEC_E_OK) { + /* Really bad. We return an empty security blob */ + OutputDebugF("AcquireCredentialsHandle failed with %lX", status); + goto nes_0; + } + + secOut.cBuffers = 1; + secOut.pBuffers = &secTok; + secOut.ulVersion = SECBUFFER_VERSION; + + secTok.BufferType = SECBUFFER_TOKEN; + secTok.cbBuffer = 0; + secTok.pvBuffer = NULL; + + ctx.dwLower = ctx.dwUpper = 0; + + status = AcceptSecurityContext( + &creds, + NULL, + NULL, + ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY, + SECURITY_NETWORK_DREP, + &ctx, + &secOut, + &flags, + &expiry + ); + + if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) { + OutputDebugF("Completing token..."); + istatus = CompleteAuthToken(&ctx, &secOut); + if ( istatus != SEC_E_OK ) + OutputDebugF("Token completion failed: %x", istatus); + } + + if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) { + if (secTok.pvBuffer) { + *secBlobLength = secTok.cbBuffer; + *secBlob = malloc( secTok.cbBuffer ); + memcpy(*secBlob, secTok.pvBuffer, secTok.cbBuffer ); + } + } else { + if ( status != SEC_E_OK ) + OutputDebugF("AcceptSecurityContext status != CONTINUE %lX", status); + } + + if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer ); + + /* Discard credentials handle. We'll reacquire one when we get the session setup X */ + FreeCredentialsHandle(&creds); + + nes_0: + + if (secBlob) { + OutputDebugF("Returning initial token:"); + OutputDebugHexDump(*secBlob,*secBlobLength); + } else { + OutputDebugF("No initial token"); + } + return; +} + +struct smb_ext_context { + CredHandle creds; + CtxtHandle ctx; + int partialTokenLen; + void * partialToken; +}; + +long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int secBlobInLength, char ** secBlobOut, int * secBlobOutLength) { + SECURITY_STATUS status, istatus; + CredHandle creds; + TimeStamp expiry; + long code = 0; + SecBufferDesc secBufIn; + SecBuffer secTokIn; + SecBufferDesc secBufOut; + SecBuffer secTokOut; + CtxtHandle ctx; + struct smb_ext_context * secCtx = NULL; + struct smb_ext_context * newSecCtx = NULL; + void * assembledBlob = NULL; + int assembledBlobLength = 0; + ULONG flags; + + OutputDebugF("In smb_AuthenticateUserExt"); + + *secBlobOut = NULL; + *secBlobOutLength = 0; + + if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) { + secCtx = vcp->secCtx; + lock_ObtainMutex(&vcp->mx); + vcp->flags &= ~SMB_VCFLAG_AUTH_IN_PROGRESS; + vcp->secCtx = NULL; + lock_ReleaseMutex(&vcp->mx); + } + + if (secBlobIn) { + OutputDebugF("Received incoming token:"); + OutputDebugHexDump(secBlobIn,secBlobInLength); + } + + if (secCtx) { + OutputDebugF("Continuing with existing context."); + creds = secCtx->creds; + ctx = secCtx->ctx; + + if (secCtx->partialToken) { + assembledBlobLength = secCtx->partialTokenLen + secBlobInLength; + assembledBlob = malloc(assembledBlobLength); + memcpy(assembledBlob,secCtx->partialToken, secCtx->partialTokenLen); + memcpy(((BYTE *)assembledBlob) + secCtx->partialTokenLen, secBlobIn, secBlobInLength); + } + } else { + status = AcquireCredentialsHandle( + NULL, + SMB_EXT_SEC_PACKAGE_NAME, + SECPKG_CRED_INBOUND, + NULL, + NULL, + NULL, + NULL, + &creds, + &expiry); + + if (status != SEC_E_OK) { + OutputDebugF("Can't acquire Credentials handle [%lX]", status); + code = CM_ERROR_BADPASSWORD; /* means "try again when I'm sober" */ + goto aue_0; + } + + ctx.dwLower = 0; + ctx.dwUpper = 0; + } + + secBufIn.cBuffers = 1; + secBufIn.pBuffers = &secTokIn; + secBufIn.ulVersion = SECBUFFER_VERSION; + + secTokIn.BufferType = SECBUFFER_TOKEN; + if (assembledBlob) { + secTokIn.cbBuffer = assembledBlobLength; + secTokIn.pvBuffer = assembledBlob; + } else { + secTokIn.cbBuffer = secBlobInLength; + secTokIn.pvBuffer = secBlobIn; + } + + secBufOut.cBuffers = 1; + secBufOut.pBuffers = &secTokOut; + secBufOut.ulVersion = SECBUFFER_VERSION; + + secTokOut.BufferType = SECBUFFER_TOKEN; + secTokOut.cbBuffer = 0; + secTokOut.pvBuffer = NULL; + + status = AcceptSecurityContext( + &creds, + ((secCtx)?&ctx:NULL), + &secBufIn, + ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY, + SECURITY_NETWORK_DREP, + &ctx, + &secBufOut, + &flags, + &expiry + ); + + if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) { + OutputDebugF("Completing token..."); + istatus = CompleteAuthToken(&ctx, &secBufOut); + if ( istatus != SEC_E_OK ) + OutputDebugF("Token completion failed: %lX", istatus); + } + + if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) { + OutputDebugF("Continue needed"); + + newSecCtx = malloc(sizeof(*newSecCtx)); + + newSecCtx->creds = creds; + newSecCtx->ctx = ctx; + newSecCtx->partialToken = NULL; + newSecCtx->partialTokenLen = 0; + + lock_ObtainMutex( &vcp->mx ); + vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS; + vcp->secCtx = newSecCtx; + lock_ReleaseMutex( &vcp->mx ); + + code = CM_ERROR_GSSCONTINUE; + } + + if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK || + status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) && + secTokOut.pvBuffer) { + OutputDebugF("Need to send token back to client"); + + *secBlobOutLength = secTokOut.cbBuffer; + *secBlobOut = malloc(secTokOut.cbBuffer); + memcpy(*secBlobOut, secTokOut.pvBuffer, secTokOut.cbBuffer); + + OutputDebugF("Outgoing token:"); + OutputDebugHexDump(*secBlobOut,*secBlobOutLength); + } else if (status == SEC_E_INCOMPLETE_MESSAGE) { + OutputDebugF("Incomplete message"); + + newSecCtx = malloc(sizeof(*newSecCtx)); + + newSecCtx->creds = creds; + newSecCtx->ctx = ctx; + newSecCtx->partialToken = malloc(secTokOut.cbBuffer); + memcpy(newSecCtx->partialToken, secTokOut.pvBuffer, secTokOut.cbBuffer); + newSecCtx->partialTokenLen = secTokOut.cbBuffer; + + lock_ObtainMutex( &vcp->mx ); + vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS; + vcp->secCtx = newSecCtx; + lock_ReleaseMutex( &vcp->mx ); + + code = CM_ERROR_GSSCONTINUE; + } + + if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) { + /* woo hoo! */ + SecPkgContext_Names names; + + OutputDebugF("Authentication completed"); + OutputDebugF("Returned flags : [%lX]", flags); + + if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) { + OutputDebugF("Received name [%s]", names.sUserName); + strcpy(usern, names.sUserName); + strlwr(usern); /* in tandem with smb_GetNormalizedUsername */ + FreeContextBuffer(names.sUserName); + } else { + /* Force the user to retry if the context is invalid */ + OutputDebugF("QueryContextAttributes Names failed [%x]", GetLastError()); + code = CM_ERROR_BADPASSWORD; + } + } else if (!code) { + switch ( status ) { + case SEC_E_INVALID_TOKEN: + OutputDebugF("Returning bad password :: INVALID_TOKEN"); + break; + case SEC_E_INVALID_HANDLE: + OutputDebugF("Returning bad password :: INVALID_HANDLE"); + break; + case SEC_E_LOGON_DENIED: + OutputDebugF("Returning bad password :: LOGON_DENIED"); + break; + case SEC_E_UNKNOWN_CREDENTIALS: + OutputDebugF("Returning bad password :: UNKNOWN_CREDENTIALS"); + break; + case SEC_E_NO_CREDENTIALS: + OutputDebugF("Returning bad password :: NO_CREDENTIALS"); + break; + case SEC_E_CONTEXT_EXPIRED: + OutputDebugF("Returning bad password :: CONTEXT_EXPIRED"); + break; + case SEC_E_INCOMPLETE_CREDENTIALS: + OutputDebugF("Returning bad password :: INCOMPLETE_CREDENTIALS"); + break; + case SEC_E_WRONG_PRINCIPAL: + OutputDebugF("Returning bad password :: WRONG_PRINCIPAL"); + break; + case SEC_E_TIME_SKEW: + OutputDebugF("Returning bad password :: TIME_SKEW"); + break; + default: + OutputDebugF("Returning bad password :: Status == %lX", status); + } + code = CM_ERROR_BADPASSWORD; + } + + if (secCtx) { + if (secCtx->partialToken) free(secCtx->partialToken); + free(secCtx); + } + + if (assembledBlob) { + free(assembledBlob); + } + + if (secTokOut.pvBuffer) + FreeContextBuffer(secTokOut.pvBuffer); + + if (code != CM_ERROR_GSSCONTINUE) { + DeleteSecurityContext(&ctx); + FreeCredentialsHandle(&creds); + } + + aue_0: + return code; +} + +#define P_LEN 256 +#define P_RESP_LEN 128 + +/* LsaLogonUser expects input parameters to be in a contiguous block of memory. + So put stuff in a struct. */ +struct Lm20AuthBlob { + MSV1_0_LM20_LOGON lmlogon; + BYTE ciResponse[P_RESP_LEN]; /* Unicode representation */ + BYTE csResponse[P_RESP_LEN]; /* ANSI representation */ + WCHAR accountNameW[P_LEN]; + WCHAR primaryDomainW[P_LEN]; + WCHAR workstationW[MAX_COMPUTERNAME_LENGTH + 1]; + TOKEN_GROUPS tgroups; + TOKEN_SOURCE tsource; +}; + +long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength) { + + NTSTATUS nts, ntsEx; + struct Lm20AuthBlob lmAuth; + PMSV1_0_LM20_LOGON_PROFILE lmprofilep; + QUOTA_LIMITS quotaLimits; + DWORD size; + ULONG lmprofilepSize; + LUID lmSession; + HANDLE lmToken; + + OutputDebugF("In smb_AuthenticateUser for user [%s] domain [%s]", accountName, primaryDomain); + OutputDebugF("ciPwdLength is %d and csPwdLength is %d", ciPwdLength, csPwdLength); + + OutputDebugF("csPassword:"); + OutputDebugHexDump(csPwd,csPwdLength); + OutputDebugF("ciPassword:"); + OutputDebugHexDump(ciPwd,ciPwdLength); + + if (ciPwdLength > P_RESP_LEN || csPwdLength > P_RESP_LEN) { + OutputDebugF("ciPwdLength or csPwdLength is too long"); + return CM_ERROR_BADPASSWORD; + } + + memset(&lmAuth,0,sizeof(lmAuth)); + + lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon; + + lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW; + mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN); + lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR); + lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR); + + lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW; + mbstowcs(lmAuth.accountNameW, accountName, P_LEN); + lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR); + lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR); + + lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW; + lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR); + size = MAX_COMPUTERNAME_LENGTH + 1; + GetComputerNameW(lmAuth.workstationW, &size); + lmAuth.lmlogon.Workstation.Length = wcslen(lmAuth.workstationW) * sizeof(WCHAR); + + memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH); + + lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Buffer = lmAuth.ciResponse; + lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Length = ciPwdLength; + lmAuth.lmlogon.CaseInsensitiveChallengeResponse.MaximumLength = P_RESP_LEN; + memcpy(lmAuth.ciResponse, ciPwd, ciPwdLength); + + lmAuth.lmlogon.CaseSensitiveChallengeResponse.Buffer = lmAuth.csResponse; + lmAuth.lmlogon.CaseSensitiveChallengeResponse.Length = csPwdLength; + lmAuth.lmlogon.CaseSensitiveChallengeResponse.MaximumLength = P_RESP_LEN; + memcpy(lmAuth.csResponse, csPwd, csPwdLength); + + lmAuth.lmlogon.ParameterControl = 0; + + lmAuth.tgroups.GroupCount = 0; + lmAuth.tgroups.Groups[0].Sid = NULL; + lmAuth.tgroups.Groups[0].Attributes = 0; + + lmAuth.tsource.SourceIdentifier.HighPart = 0; + lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp; + strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */ + + nts = LsaLogonUser( + smb_lsaHandle, + &smb_lsaLogonOrigin, + Network, /*3*/ + smb_lsaSecPackage, + &lmAuth, + sizeof(lmAuth), + &lmAuth.tgroups, + &lmAuth.tsource, + &lmprofilep, + &lmprofilepSize, + &lmSession, + &lmToken, + "aLimits, + &ntsEx); + + OutputDebugF("Return from LsaLogonUser is 0x%lX", nts); + OutputDebugF("Extended status is 0x%lX", ntsEx); + + if (nts == ERROR_SUCCESS) { + /* free the token */ + LsaFreeReturnBuffer(lmprofilep); + CloseHandle(lmToken); + return 0; + } else { + /* No AFS for you */ + if (nts == 0xC000015BL) + return CM_ERROR_BADLOGONTYPE; + else /* our catchall is a bad password though we could be more specific */ + return CM_ERROR_BADPASSWORD; + } +} + +/* The buffer pointed to by usern is assumed to be at least SMB_MAX_USERNAME_LENGTH bytes */ +long smb_GetNormalizedUsername(char * usern, const char * accountName, const char * domainName) { + + char * atsign; + const char * domain; + + /* check if we have sane input */ + if ((strlen(accountName) + strlen(domainName) + 1) > SMB_MAX_USERNAME_LENGTH) + return 1; + + /* we could get : [accountName][domainName] + [user][domain] + [user@domain][] + [user][]/[user][?] + [][]/[][?] */ + + atsign = strchr(accountName, '@'); + + if (atsign) /* [user@domain][] -> [user@domain][domain] */ + domain = atsign + 1; + else + domain = domainName; + + /* if for some reason the client doesn't know what domain to use, + it will either return an empty string or a '?' */ + if (!domain[0] || domain[0] == '?') + /* Empty domains and empty usernames are usually sent from tokenless contexts. + This way such logins will get an empty username (easy to check). I don't know + when a non-empty username would be supplied with an anonymous domain, but *shrug* */ + strcpy(usern,accountName); + else { + /* TODO: what about WIN.MIT.EDU\user vs. WIN\user? */ + strcpy(usern,domain); + strcat(usern,"\\"); + if (atsign) + strncat(usern,accountName,atsign - accountName); + else + strcat(usern,accountName); + } + + strlwr(usern); + + return 0; +} + +/* When using SMB auth, all SMB sessions have to pass through here first to + * authenticate the user. + * Caveat: If not use the SMB auth the protocol does not require sending a + * session setup packet, which means that we can't rely on a UID in subsequent + * packets. Though in practice we get one anyway. + */ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *tp; - char *usern, *pwd, *pwdx; smb_user_t *uidp; unsigned short newUid; - unsigned long caps; + unsigned long caps = 0; cm_user_t *userp; smb_username_t *unp; char *s1 = " "; + long code = 0; + char usern[SMB_MAX_USERNAME_LENGTH]; + char *secBlobOut = NULL; + int secBlobOutLength = 0; /* Check for bad conns */ if (vcp->flags & SMB_VCFLAG_REMOTECONN) return CM_ERROR_REMOTECONN; - /* For NT LM 0.12 and up, get capabilities */ if (vcp->flags & SMB_VCFLAG_USENT) { - caps = smb_GetSMBParm(inp, 11); - if (caps & 0x40) + if (smb_authType == SMB_AUTH_EXTENDED) { + /* extended authentication */ + char *secBlobIn; + int secBlobInLength; + + if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) { + caps = smb_GetSMBParm(inp,10) | (((unsigned long) smb_GetSMBParm(inp,11)) << 16); + } + + secBlobInLength = smb_GetSMBParm(inp, 7); + secBlobIn = smb_GetSMBData(inp, NULL); + + code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength); + + if (code == CM_ERROR_GSSCONTINUE) { + smb_SetSMBParm(outp, 2, 0); + smb_SetSMBParm(outp, 3, secBlobOutLength); + smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + tp = smb_GetSMBData(outp, NULL); + if (secBlobOutLength) { + memcpy(tp, secBlobOut, secBlobOutLength); + free(secBlobOut); + tp += secBlobOutLength; + } + memcpy(tp,smb_ServerOS,smb_ServerOSLength); + tp += smb_ServerOSLength; + memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); + tp += smb_ServerLanManagerLength; + memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); + tp += smb_ServerDomainNameLength; + } + + /* TODO: handle return code and continue auth. Also free secBlobOut if applicable. */ + } else { + unsigned ciPwdLength, csPwdLength; + char *ciPwd, *csPwd; + char *accountName; + char *primaryDomain; + int datalen; + + /* TODO: parse for extended auth as well */ + ciPwdLength = smb_GetSMBParm(inp, 7); /* case insensitive password length */ + csPwdLength = smb_GetSMBParm(inp, 8); /* case sensitive password length */ + + tp = smb_GetSMBData(inp, &datalen); + + OutputDebugF("Session packet data size [%d]",datalen); + + ciPwd = tp; + tp += ciPwdLength; + csPwd = tp; + tp += csPwdLength; + + accountName = smb_ParseString(tp, &tp); + primaryDomain = smb_ParseString(tp, NULL); + + if (smb_GetNormalizedUsername(usern, accountName, primaryDomain)) { + /* shouldn't happen */ + code = CM_ERROR_BADSMB; + goto after_read_packet; + } + + /* capabilities are only valid for first session packet */ + if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) { + caps = smb_GetSMBParm(inp, 11) | (((unsigned long)smb_GetSMBParm(inp, 12)) << 16); + } + + if (smb_authType == SMB_AUTH_NTLM) { + code = smb_AuthenticateUserLM(vcp, accountName, primaryDomain, ciPwd, ciPwdLength, csPwd, csPwdLength); + } + } + } else { /* V3 */ + unsigned ciPwdLength; + char *ciPwd; + char *accountName; + char *primaryDomain; + + ciPwdLength = smb_GetSMBParm(inp, 7); + tp = smb_GetSMBData(inp, NULL); + ciPwd = tp; + tp += ciPwdLength; + + accountName = smb_ParseString(tp, &tp); + primaryDomain = smb_ParseString(tp, NULL); + + if ( smb_GetNormalizedUsername(usern, accountName, primaryDomain)) { + /* shouldn't happen */ + code = CM_ERROR_BADSMB; + goto after_read_packet; + } + + /* even if we wanted extended auth, if we only negotiated V3, we have to fallback + * to NTLM. + */ + if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) { + code = smb_AuthenticateUserLM(vcp,accountName,primaryDomain,ciPwd,ciPwdLength,"",0); + } + } + + after_read_packet: + /* note down that we received a session setup X and set the capabilities flag */ + if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) { + lock_ObtainMutex(&vcp->mx); + vcp->flags |= SMB_VCFLAG_SESSX_RCVD; + /* for the moment we can only deal with NTSTATUS */ + if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) { vcp->flags |= SMB_VCFLAG_STATUS32; - /* for now, ignore other capability bits */ - } + } + lock_ReleaseMutex(&vcp->mx); + } + + /* code would be non-zero if there was an authentication failure. + Ideally we would like to invalidate the uid for this session or break + early to avoid accidently stealing someone else's tokens. */ - /* Parse the data */ - tp = smb_GetSMBData(inp, NULL); - if (vcp->flags & SMB_VCFLAG_USENT) - pwdx = smb_ParseString(tp, &tp); - pwd = smb_ParseString(tp, &tp); - usern = smb_ParseString(tp, &tp); + if (code) { + return code; + } + + OutputDebugF("Received username=[%s]", usern); /* On Windows 2000, this function appears to be called more often than it is expected to be called. This resulted in multiple smb_user_t @@ -189,8 +843,43 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * osi_Log3(smb_logp, "SMB3 session setup name %s creating ID %d%s", osi_LogSaveString(smb_logp, usern), newUid, osi_LogSaveString(smb_logp, s1)); + smb_SetSMBParm(outp, 2, 0); - smb_SetSMBDataLength(outp, 0); + + if (vcp->flags & SMB_VCFLAG_USENT) { + if (smb_authType == SMB_AUTH_EXTENDED) { + smb_SetSMBParm(outp, 3, secBlobOutLength); + smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + tp = smb_GetSMBData(outp, NULL); + if (secBlobOutLength) { + memcpy(tp, secBlobOut, secBlobOutLength); + free(secBlobOut); + tp += secBlobOutLength; + } + memcpy(tp,smb_ServerOS,smb_ServerOSLength); + tp += smb_ServerOSLength; + memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); + tp += smb_ServerLanManagerLength; + memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); + tp += smb_ServerDomainNameLength; + } else { + smb_SetSMBDataLength(outp, 0); + } + } else { + if (smb_authType == SMB_AUTH_EXTENDED) { + smb_SetSMBDataLength(outp, smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + tp = smb_GetSMBData(outp, NULL); + memcpy(tp,smb_ServerOS,smb_ServerOSLength); + tp += smb_ServerOSLength; + memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); + tp += smb_ServerLanManagerLength; + memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); + tp += smb_ServerDomainNameLength; + } else { + smb_SetSMBDataLength(outp, 0); + } + } + return 0; } @@ -212,10 +901,8 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou if (s2 == NULL) s2 = " "; if (s1 == NULL) {s1 = s2; s2 = " ";} - osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", - uidp->userID, - osi_LogSaveString(smb_logp, - (uidp->unp) ? uidp->unp->name: " "), s1, s2); + osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID, + osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2); lock_ObtainMutex(&uidp->mx); uidp->flags |= SMB_USERFLAG_DELETE; @@ -742,7 +1429,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) userp = smb_GetTran2User(vcp, p); /* In the off chance that userp is NULL, we log and abandon */ - if(!userp) { + if (!userp) { osi_Log1(smb_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid); smb_FreeTran2Packet(outp); return CM_ERROR_BADSMB; @@ -1165,7 +1852,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t } userp = smb_GetTran2User(vcp, p); - if(!userp) { + if (!userp) { osi_Log1(smb_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid); smb_FreeTran2Packet(outp); return CM_ERROR_BADSMB; @@ -1366,7 +2053,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t outp->totalData = nbytesRequired; userp = smb_GetTran2User(vcp, p); - if(!userp) { + if (!userp) { osi_Log1(smb_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid); code = CM_ERROR_BADSMB; goto done; @@ -1480,7 +2167,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet outp->totalData = 0; userp = smb_GetTran2User(vcp, p); - if(!userp) { + if (!userp) { osi_Log1(smb_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid); code = CM_ERROR_BADSMB; goto done; @@ -1677,7 +2364,7 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp, /* Copy attributes */ lattr = smb_ExtAttributes(scp); /* merge in hidden (dot file) attribute */ - if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) + if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) lattr |= SMB_ATTR_HIDDEN; *((u_long *)dptr) = lattr; dptr += 4; @@ -1727,7 +2414,7 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp, /* finally copy out attributes as short */ attr = smb_Attributes(scp); /* merge in hidden (dot file) attribute */ - if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) + if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) attr |= SMB_ATTR_HIDDEN; *dptr++ = attr & 0xff; *dptr++ = (attr >> 8) & 0xff; @@ -2469,7 +3156,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t } } /* if we're including this name */ - else if(!NeedShortName && + else if (!NeedShortName && !starPattern && !foundInexact && dep->fid.vnode != 0 && @@ -3411,7 +4098,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) treeStartp = realPathp + (tp - spacep->data); if (*tp && !smb_IsLegalFilename(tp)) { - if(baseFid != 0) + if (baseFid != 0) smb_ReleaseFID(baseFidp); cm_ReleaseUser(userp); free(realPathp); @@ -3455,7 +4142,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) } if (!foundscp && !treeCreate) { - if(createDisp == 2 || createDisp == 4) + if (createDisp == 2 || createDisp == 4) code = cm_Lookup(dscp, lastNamep, CM_FLAG_FOLLOW, userp, &req, &scp); else @@ -3571,9 +4258,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) cp = spacep->data; tscp = dscp; - while(pp && *pp) { + while (pp && *pp) { tp = strchr(pp, '\\'); - if(!tp) { + if (!tp) { strcpy(cp,pp); clen = strlen(cp); isLast = 1; /* indicate last component. the supplied path never ends in a slash */ @@ -3586,7 +4273,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) } pp = tp; - if(clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */ + if (clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */ /* cp is the next component to be created. */ code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req); @@ -3605,9 +4292,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD, userp, &req, &scp); } - if(code) break; + if (code) break; - if(!isLast) { /* for anything other than dscp, release it unless it's the last one */ + if (!isLast) { /* for anything other than dscp, release it unless it's the last one */ cm_ReleaseSCache(tscp); tscp = scp; /* Newly created directory will be next parent */ } @@ -3840,7 +4527,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out #endif userp = smb_GetUser(vcp, inp); - if(!userp) { + if (!userp) { osi_Log1(smb_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid); free(realPathp); return CM_ERROR_INVAL; @@ -3852,7 +4539,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out } else { baseFidp = smb_FindFID(vcp, baseFid, 0); - if(!baseFidp) { + if (!baseFidp) { osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid); free(realPathp); cm_ReleaseUser(userp); diff --git a/src/WINNT/afsd/smb3.h b/src/WINNT/afsd/smb3.h index 72b945a..beaf37a 100644 --- a/src/WINNT/afsd/smb3.h +++ b/src/WINNT/afsd/smb3.h @@ -168,6 +168,9 @@ extern int smb_V3MatchMask(char *namep, char *maskp, int flags); extern void smb3_Init(); extern cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine); +/* SMB auth related functions */ +extern void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength); + #ifdef DJGPP #define DELETE (0x00010000) #define READ_CONTROL (0x00020000) diff --git a/src/WINNT/install/NSIS/AFSCell.ini b/src/WINNT/install/NSIS/AFSCell.ini index e410d6f..9c09ef1 100644 --- a/src/WINNT/install/NSIS/AFSCell.ini +++ b/src/WINNT/install/NSIS/AFSCell.ini @@ -1,5 +1,5 @@ [Settings] -NumFields=13 +NumFields=11 [Field 1] Type=label @@ -49,15 +49,15 @@ Right=-1 Top=65 Bottom=75 -[Field 11] +[Field 9] Type=Checkbox -State=0 +State=1 Left=50 Right=60 Top=75 Bottom=85 -[Field 12] +[Field 10] Type=label Text=Use DNS to Search for Cell Servers Left=65 @@ -81,23 +81,7 @@ Right=-1 Top=85 Bottom=95 -[Field 9] -Type=Checkbox -State=0 -Left=50 -Right=60 -Top=95 -Bottom=105 - -[Field 10] -Type=label -Text=Enable Integrated Logon high security -Left=65 -Right=-1 -Top=95 -Bottom=105 - -[Field 13] +[Field 11] Type=label Text=You may now configure some installation options that control how the AFS Client behaves. Left=35 diff --git a/src/WINNT/install/NSIS/OpenAFS.nsi b/src/WINNT/install/NSIS/OpenAFS.nsi index bf4bb79..8da7af4 100644 --- a/src/WINNT/install/NSIS/OpenAFS.nsi +++ b/src/WINNT/install/NSIS/OpenAFS.nsi @@ -676,11 +676,7 @@ skipremove: ; to also include the service name. Call AddProvider ReadINIStr $R0 $1 "Field 7" "State" - ReadINIStr $R1 $1 "Field 9" "State" - ; Complicated way to do $R1 = ($R1 *2) + $R0 - IntOp $R2 $R1 * 2 - IntOp $R1 $R2 + $R0 - WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "LogonOptions" $R1 + WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "LogonOptions" $R0 WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "LogonScript" "$INSTDIR\Client\Program\afscreds.exe -:%s -x -a -m -n -q" WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\NetworkProvider" "Name" "OpenAFSDaemon" @@ -692,7 +688,7 @@ skipremove: WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "SecurityLevel" $R0 ReadINIStr $R0 $1 "Field 5" "State" WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "FreelanceClient" $R0 - ReadINIStr $R0 $1 "Field 11" "State" + ReadINIStr $R0 $1 "Field 9" "State" WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "UseDNS" $R0 WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "NetbiosName" "AFS" WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\TransarcAFSDaemon\Parameters" "MountRoot" "/afs" @@ -717,6 +713,27 @@ skipremove: strcpy $REG_DATA_3 "RpcSs" Call RegWriteMultiStr + ; The following are keys added for Terminal Server compatibility + ; http://support.microsoft.com/default.aspx?scid=kb;EN-US;186499 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afsd_service.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afsshare.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klog.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\tokens.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\aklog.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\unlog.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\fs.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afscreds.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\symlink.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\pts.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\bos.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kas.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\vos.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\udebug.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\translate_et.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\rxdebug.exe" "Flags" 0x408 + WriteRegDWORD HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\backup.exe" "Flags" 0x408 + SetRebootFlag true WriteUninstaller "$INSTDIR\Uninstall.exe" @@ -1959,6 +1976,27 @@ StartRemove: DeleteRegKey HKCR "FOLDER\shellex\ContextMenuHandlers\AFS Client Shell Extension" DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved" "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}" + ; The following are keys added for Terminal Server compatibility + ; http://support.microsoft.com/default.aspx?scid=kb;EN-US;186499 + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afsd_service.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afsshare.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\klog.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\tokens.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\aklog.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\unlog.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\fs.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\afscreds.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\symlink.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kpasswd.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\pts.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\bos.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\kas.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\vos.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\udebug.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\translate_et.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\rxdebug.exe" + DeleteRegKey HKLM "Software\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\backup.exe" + DeleteRegKey HKLM "${AFS_REGKEY_ROOT}\AFS Client\CurrentVersion" DeleteRegKey HKLM "${AFS_REGKEY_ROOT}\AFS Client" DeleteRegKey HKLM "${AFS_REGKEY_ROOT}\AFS Supplemental Documentation\CurrentVersion" diff --git a/src/config/NTMakefile.i386_nt40 b/src/config/NTMakefile.i386_nt40 index 7ab2fe6..f1c7c73 100644 --- a/src/config/NTMakefile.i386_nt40 +++ b/src/config/NTMakefile.i386_nt40 @@ -79,7 +79,7 @@ LIB = $(AFSDEV_LIB) #define used in WinNT/2000 installation and program version display AFSPRODUCT_VER_MAJOR=1 AFSPRODUCT_VER_MINOR=3 -AFSPRODUCT_VER_PATCH=6500 +AFSPRODUCT_VER_PATCH=6590 AFSPRODUCT_VER_BUILD=0 AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH) AFSPRODUCT_FILE_VERSION=$(AFSPRODUCT_VER_MAJOR),$(AFSPRODUCT_VER_MINOR),$(AFSPRODUCT_VER_PATCH),$(AFSPRODUCT_VER_BUILD) diff --git a/src/rxkad/rxkad.p.h b/src/rxkad/rxkad.p.h index 06004bd..8e72043 100644 --- a/src/rxkad/rxkad.p.h +++ b/src/rxkad/rxkad.p.h @@ -22,8 +22,10 @@ #define KTC_TIME_UNCERTAINTY (15*60) /* max skew bet. machines' clocks */ #define MAXRANDOMNAMELEN 16 /* length of random generated - * usernames used by afslog for high - * security must be < MAXKTCNAMELEN */ + * usernames used by afslog for high + * security must be < MAXKTCNAMELEN && < MAXSMBNAMELEN */ +#define MAXSMBNAMELEN 256 /* max length of an SMB name */ + #define LOGON_OPTION_INTEGRATED 1 #define LOGON_OPTION_HIGHSECURITY 2 @@ -56,7 +58,7 @@ struct ktc_principal { char instance[MAXKTCNAMELEN]; char cell[MAXKTCREALMLEN]; #ifdef AFS_NT40_ENV - char smbname[MAXRANDOMNAMELEN]; + char smbname[MAXSMBNAMELEN]; #endif }; -- 1.9.4