secur32: A base64 codec for communication with ntlm_auth

Kai Blin blin at gmx.net
Tue Sep 6 06:06:32 CDT 2005


secur32.dll is planned to use ntlm_auth to take care of NTLM and
Negotiate style authentication. As ntlm_auth was developed for the Squid
proxy, it uses the Squid helper protocol for communication. This relies
on sending data back and forth in base64. Unlike the base64 code in
wininet's http.c, this version also decodes base64 code.

Changelog:
Kai Blin  <blin at gmx.net>
Added base64 codec for communication with ntlm_auth.

-- 
Kai Blin, (blin at gmx dot net)
Weekends were made for programming.
- Karl Lehenbauer
-------------- next part --------------
Index: dlls/secur32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/secur32/Makefile.in,v
retrieving revision 1.6
diff -u -3 -r1.6 Makefile.in
--- dlls/secur32/Makefile.in	17 Aug 2005 09:52:30 -0000	1.6
+++ dlls/secur32/Makefile.in	6 Sep 2005 10:03:53 -0000
@@ -7,6 +7,7 @@
 IMPORTS   = user32 advapi32 kernel32 ntdll
 
 C_SRCS = \
+	base64_codec.c \
 	negotiate.c \
 	ntlm.c \
 	schannel.c \
Index: dlls/secur32/secur32_priv.h
===================================================================
RCS file: /home/wine/wine/dlls/secur32/secur32_priv.h,v
retrieving revision 1.5
diff -u -3 -r1.5 secur32_priv.h
--- dlls/secur32/secur32_priv.h	30 Aug 2005 08:55:20 -0000	1.5
+++ dlls/secur32/secur32_priv.h	6 Sep 2005 10:03:54 -0000
@@ -86,4 +86,11 @@
 void SECUR32_initNegotiateSP(void);
 void SECUR32_initNTLMSP(void);
 
+/* Functions from base64_codec.c used elsewhere */
+SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char* out_buf, 
+        int max_len, int *out_len);
+
+SECURITY_STATUS decodeBase64(char *in_buf, int in_len, BYTE *out_buf, 
+        int max_len, int *out_len);
+
 #endif /* ndef __SECUR32_PRIV_H__ */
--- /dev/null	2005-08-30 09:02:02.639199272 +0200
+++ dlls/secur32/base64_codec.c	2005-08-31 09:59:58.000000000 +0200
@@ -0,0 +1,179 @@
+/* 
+ * base64 encoder/decoder
+ *
+ * Copyright 2005 by Kai Blin
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "windef.h"
+#include "winerror.h"
+#include "sspi.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(secur32);
+
+static const char b64[] = 
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char* out_buf,
+        int max_len, int *out_len)
+{
+    int div, i;
+    PBYTE d = in_buf;
+    int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
+
+    TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
+    *out_len = bytes + pad_bytes;
+
+    if(bytes + pad_bytes + 1 > max_len)
+        return SEC_E_BUFFER_TOO_SMALL;
+    
+    /* Three bytes of input give 4 chars of output */
+    div = in_len / 3;
+
+    i = 0;
+    while(div > 0)
+    {
+        /* first char is the first 6 bits of the first byte*/
+        out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
+        /* second char is the last 2 bits of the first byte and the first 4
+         * bits of the second byte */
+        out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+        /* third char is the last 4 bits of the second byte and the first 2
+         * bits of the third byte */
+        out_buf[i + 2] = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
+        /* fourth char is the remaining 6 bits of the third byte */
+        out_buf[i + 3] = b64[   d[2]       & 0x3f];
+        i += 4;
+        d += 3;
+        div--;
+    }
+    
+    switch(pad_bytes)
+    {
+        case 1: 
+            /* first char is the first 6 bits of the first byte*/
+            out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte and the first 4
+             * bits of the second byte */
+            out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+            /* third char is the last 4 bits of the second byte padded with 
+             * two zeroes */
+            out_buf[i + 2] = b64[ ((d[1] >> 4) & 0x3c) ];
+            /* fourth char is a = to indicate one byte of padding */
+            out_buf[i + 3] = '=';
+            out_buf[i + 4] = 0;
+            break;
+        case 2:
+            /* first char is the first 6 bits of the first byte*/
+            out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte padded with 
+             * four zeroes*/
+            out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30)];
+            /* third char is = to indicate padding */
+            out_buf[i + 2] = '=';
+            /* fourth char is = to indicate padding */
+            out_buf[i + 3] = '=';
+            out_buf[i + 4] = 0;
+            break;
+        default:
+            out_buf[i] = 0;
+    }
+        
+    return SEC_E_OK;
+}
+
+BYTE decode(char c)
+{
+    if( c >= 'A' && c <= 'Z')
+        return c - 'A';
+    if( c >= 'a' && c <= 'z')
+        return c - 'a' + 26;
+    if( c >= '0' && c <= '9')
+        return c - '0' + 52;
+    if( c == '+')
+        return 62;
+    if( c == '/')
+        return 63;
+    else
+        return 64;
+}
+
+SECURITY_STATUS decodeBase64(char *in_buf, int in_len, PBYTE out_buf, 
+        int max_len, int *out_len)
+{
+    int len = in_len, i;
+    char *d = in_buf;
+    int  ip0, ip1, ip2, ip3;
+
+    TRACE("in_len: %d\n", in_len);
+
+    if((in_len % 4) != 0)
+        return SEC_E_INVALID_TOKEN;
+
+    if(in_len > max_len)
+        return SEC_E_BUFFER_TOO_SMALL;
+
+    i = 0;
+    while(len > 4)
+    {
+        ip0 = decode(d[0]);
+        ip1 = decode(d[1]);
+        ip2 = decode(d[2]);
+        ip3 = decode(d[3]);
+        
+        out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
+        out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
+        out_buf[i + 2] = (ip2 << 6) |  ip3;
+        len -= 4;
+        i += 3;
+        d += 4;
+    }
+
+    if(d[2] == '=')
+    {
+        ip0 = decode(d[0]);
+        ip1 = decode(d[1]);
+
+        out_buf[i] = (ip0 << 2) | (ip1 >> 4);
+        i++;      
+    }
+    else if(d[3] == '=')
+    {
+        ip0 = decode(d[0]);
+        ip1 = decode(d[1]);
+        ip2 = decode(d[2]);
+
+        out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
+        out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
+        i += 2;
+    }
+    else
+    {
+        ip0 = decode(d[0]);
+        ip1 = decode(d[1]);
+        ip2 = decode(d[2]);
+        ip3 = decode(d[3]);
+
+        out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
+        out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
+        out_buf[i + 2] = (ip2 << 6) |  ip3;
+        i += 3;
+    }
+    *out_len = i;        
+    return SEC_E_OK;
+}
+


More information about the wine-patches mailing list