smb-extended-20040724
[openafs.git] / src / WINNT / afsd / smb.c
index 46df33e..3d6448e 100644 (file)
@@ -9,8 +9,6 @@
 
 //#define NOSERVICE 1
 
-#define NOMOREFILESFIX 1
-
 #include <afs/param.h>
 #include <afs/stds.h>
 
@@ -28,6 +26,7 @@
 #include <time.h>
 
 #include <osi.h>
+#include <ntstatus.h>
 
 #include "afsd.h"
 
@@ -87,6 +86,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 +191,16 @@ 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);
+
+/* Faux server GUID. This is never checked. */
+GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+
 /*
  * Demo expiration
  *
@@ -251,6 +265,10 @@ char * myCrt_Dispatch(int i)
                return "(23)ReceiveV3GetAttributes";
        case 0x24:
                return "(24)ReceiveV3LockingX";
+       case 0x25:
+               return "(25)ReceiveV3Trans";
+       case 0x26:
+               return "(26)ReceiveV3Trans[aux]";
        case 0x29:
                return "(29)SendCoreBadOp";
        case 0x2b:
@@ -262,7 +280,7 @@ char * myCrt_Dispatch(int i)
        case 0x32:
                return "(32)ReceiveV3Tran2A";
        case 0x33:
-               return "(33)ReceiveV3Tran2A";
+               return "(33)ReceiveV3Tran2A[aux]";
        case 0x34:
                return "(34)ReceiveV3FindClose";
        case 0x35:
@@ -337,6 +355,23 @@ char * myCrt_2Dispatch(int i)
        }
 }
 
+char * myCrt_RapDispatch(int i)
+{
+       switch(i)
+       {
+       default:
+               return "unknown RAP OP";
+       case 0:
+               return "RAP(0)NetShareEnum";
+       case 1:
+               return "RAP(1)NetShareGetInfo";
+       case 13:
+               return "RAP(13)NetServerGetInfo";
+       case 63:
+               return "RAP(63)NetWkStaGetInfo";
+       }
+}
+
 /* scache must be locked */
 unsigned int smb_Attributes(cm_scache_t *scp)
 {
@@ -738,6 +773,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;
@@ -1136,6 +1198,7 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
+#ifdef DJGPP
 /* List available shares */
 int smb_ListShares()
 {
@@ -1199,7 +1262,7 @@ int smb_ListShares()
 
        return num_shares;
 }
-
+#endif /* DJGPP */
 /* find a shareName in the table of submounts */
 int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        char **pathNamep)
@@ -1209,7 +1272,9 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        char *var;
        char temp[1024];
        DWORD sizeTemp;
+#ifdef DJGPP
     char sbmtpath[MAX_PATH];
+#endif
     char *p, *q;
        HKEY parmKey;
        DWORD code;
@@ -1251,13 +1316,24 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        }
 
 #ifndef DJGPP
-    strcpy(sbmtpath, "afsdsbmt.ini");
+       code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
+                                               0, KEY_QUERY_VALUE, &parmKey);
+       if (code == ERROR_SUCCESS) {
+        len = sizeof(pathName);
+        code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
+                                (BYTE *) pathName, &len);
+               if (code != ERROR_SUCCESS)
+                       len = 0;
+        RegCloseKey (parmKey);
+       } else {
+        len = 0;
+    }   
 #else /* DJGPP */
     strcpy(sbmtpath, cm_confDir);
     strcat(sbmtpath, "/afsdsbmt.ini");
-#endif /* !DJGPP */
        len = GetPrivateProfileString("AFS Submounts", shareName, "",
                                   pathName, sizeof(pathName), sbmtpath);
+#endif /* !DJGPP */
        if (len != 0 && len != sizeof(pathName) - 1) {
         /* We can accept either unix or PC style AFS pathnames.  Convert
          * Unix-style to PC style here for internal use. 
@@ -1346,36 +1422,40 @@ int smb_FindShareCSCPolicy(char *shareName)
 {
        DWORD len;
        char policy[1024];
-       char sbmtpath[256];
-
-#ifndef DJGPP
-        strcpy(sbmtpath, "afsdsbmt.ini");
-#else /* DJGPP */
-        strcpy(sbmtpath, cm_confDir);
-        strcat(sbmtpath, "/afsdsbmt.ini");
-#endif /* !DJGPP */
-       len = GetPrivateProfileString("CSC Policy", shareName, "",
-                                     policy, sizeof(policy), sbmtpath);
-       if (len == 0 || len == sizeof(policy) - 1) {
-               return CSC_POLICY_MANUAL;
-       }
-       
-       if (stricmp(policy, "documents") == 0)
+    DWORD dwType;
+    HKEY hkCSCPolicy;
+    int  retval = CSC_POLICY_MANUAL;
+
+    RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                    "SOFTWARE\\OpenAFS\\Client\\CSCPolicy",
+                    0, 
+                    "AFS", 
+                    REG_OPTION_NON_VOLATILE,
+                    KEY_READ,
+                    NULL, 
+                    &hkCSCPolicy,
+                    NULL );
+
+    len = sizeof(policy);
+    if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
+         len == 0) {
+               retval = CSC_POLICY_MANUAL;
+    }
+       else if (stricmp(policy, "documents") == 0)
        {
-               return CSC_POLICY_DOCUMENTS;
+               retval = CSC_POLICY_DOCUMENTS;
        }
-       
-       if (stricmp(policy, "programs") == 0)
+       else if (stricmp(policy, "programs") == 0)
        {
-               return CSC_POLICY_PROGRAMS;
+               retval = CSC_POLICY_PROGRAMS;
        }
-       
-       if (stricmp(policy, "disable") == 0)
+       else if (stricmp(policy, "disable") == 0)
        {
-               return CSC_POLICY_DISABLE;
+               retval = CSC_POLICY_DISABLE;
        }
        
-       return CSC_POLICY_MANUAL;
+    RegCloseKey(hkCSCPolicy);
+       return retval;
 }
 
 /* find a dir search structure by cookie value, and return it held.
@@ -2097,6 +2177,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 +2337,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 +2517,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) {
@@ -2490,43 +2588,6 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         namep += entryLength;
         tcounter++;            /* which proto entry we're looking at */
        }
-#ifndef NOMOREFILESFIX
-       /* 
-        * NOTE: We can determine what OS (NT4.0, W2K, W9X, etc)
-        * the client is running by reading the protocol signature.
-        * ie. the order in which it sends us the protocol list.
-        *
-        * Special handling for Windows 2000 clients (defect 11765 )
-     * <asanka:11Jun03> Proto signature is the same for Win XP. </>
-        */
-       if (tcounter == 6) {
-               int i = 0;
-               smb_t *ip = (smb_t *) inp;
-               smb_t *op = (smb_t *) outp;
-
-               if ((strcmp("PC NETWORK PROGRAM 1.0", protocol_array[0]) == 0) &&
-                        (strcmp("LANMAN1.0", protocol_array[1]) == 0) &&
-                        (strcmp("Windows for Workgroups 3.1a", protocol_array[2]) == 0) &&
-                        (strcmp("LM1.2X002", protocol_array[3]) == 0) &&
-                        (strcmp("LANMAN2.1", protocol_array[4]) == 0) &&
-                        (strcmp("NT LM 0.12", protocol_array[5]) == 0)) {
-                       isWindows2000 = TRUE;
-                       osi_Log0(smb_logp, "Looks like a Windows 2000 client");
-                       /* 
-                        * HACK: for now - just negotiate a lower protocol till we 
-                        * figure out which flag/flag2 or some other field 
-                        * (capabilities maybe?) to set in order for this to work
-                        * correctly with Windows 2000 clients (defect 11765)
-                        */
-                       NTProtoIndex = -1;
-                       /* Things to try (after looking at tcpdump output could be
-                        * setting flags and flags2 to 0x98 and 0xc853 like this
-                        * op->reb = 0x98; op->flg2 = 0xc853;
-                        * osi_Log2(smb_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
-                        */
-               }       
-       }       
-#endif /* NOMOREFILESFIX */
 
        if (NTProtoIndex != -1) {
                protoIndex = NTProtoIndex;
@@ -2545,12 +2606,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 +2640,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 +2747,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 +5977,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;
@@ -7084,6 +7241,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0x23].procp = smb_ReceiveV3GetAttributes;
        smb_dispatchTable[0x24].procp = smb_ReceiveV3LockingX;
        smb_dispatchTable[0x24].flags |= SMB_DISPATCHFLAG_CHAINED;
+       smb_dispatchTable[0x25].procp = smb_ReceiveV3Trans;
+       smb_dispatchTable[0x25].flags |= SMB_DISPATCHFLAG_NORESPONSE;
+       smb_dispatchTable[0x26].procp = smb_ReceiveV3Trans;
+       smb_dispatchTable[0x26].flags |= SMB_DISPATCHFLAG_NORESPONSE;
        smb_dispatchTable[0x29].procp = smb_SendCoreBadOp;      /* copy file */
        smb_dispatchTable[0x2b].procp = smb_ReceiveCoreEcho;
        /* Set NORESPONSE because smb_ReceiveCoreEcho() does the responses itself */
@@ -7138,8 +7299,87 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
        smb_tran2DispatchTable[13].procp = smb_ReceiveTran2MKDir;
 
+    /* setup the rap dispatch table */
+    memset(smb_rapDispatchTable, 0, sizeof(smb_rapDispatchTable));
+    smb_rapDispatchTable[0].procp = smb_ReceiveRAPNetShareEnum;
+    smb_rapDispatchTable[1].procp = smb_ReceiveRAPNetShareGetInfo;
+    smb_rapDispatchTable[63].procp = smb_ReceiveRAPNetWkstaGetInfo;
+    smb_rapDispatchTable[13].procp = smb_ReceiveRAPNetServerGetInfo;
+
        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*/
+
+               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) {
+                               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;
+               } 
+#ifdef COMMENT
+        /* Don't fallback to SMB_AUTH_NTLM.  Apparently, allowing SPNEGO to be used each
+         * time prevents the failure of authentication when logged into Windows with an
+         * external Kerberos principal mapped to a local account.
+         */
+        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);
+        }
+#endif
+       }
+
+       {
+               DWORD bufsize;
+               /* 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);
+       }
+
        /* Start listeners, waiters, servers, and daemons */
 
        for (i = 0; i < lana_list.length; i++) {