RIP BOOL. Convert BOOL -> bool. I found a few interesting
[nivanova/samba-autobuild/.git] / source3 / libsmb / spnego.c
index 078191ffba24bb6b3b53e0ed8b27a52afbc024f1..57b2d8060bd1909004bfd640f5d4b9b1034d0a98 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
 
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -26,7 +25,7 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
 
-static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
+static bool read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
 {
        ZERO_STRUCTP(token);
 
@@ -42,13 +41,18 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
                        asn1_start_tag(asn1, ASN1_CONTEXT(0));
                        asn1_start_tag(asn1, ASN1_SEQUENCE(0));
 
-                       token->mechTypes = malloc(sizeof(*token->mechTypes));
+                       token->mechTypes = SMB_MALLOC_P(const char *);
                        for (i = 0; !asn1->has_error &&
                                     0 < asn1_tag_remaining(asn1); i++) {
+                               char *p_oid = NULL;
                                token->mechTypes = 
-                                       realloc(token->mechTypes, (i + 1) *
-                                               sizeof(*token->mechTypes));
-                               asn1_read_OID(asn1, token->mechTypes + i);
+                                       SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2);
+                               if (!token->mechTypes) {
+                                       asn1->has_error = True;
+                                       return False;
+                               }
+                               asn1_read_OID(asn1, &p_oid);
+                               token->mechTypes[i] = p_oid;
                        }
                        token->mechTypes[i] = NULL;
                        
@@ -71,7 +75,12 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
                /* Read mecListMIC */
                case ASN1_CONTEXT(3):
                        asn1_start_tag(asn1, ASN1_CONTEXT(3));
-                       if (!asn1_read_OctetString(asn1, &token->mechListMIC)) {
+                       if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) {
+                               asn1_read_OctetString(asn1,
+                                                     &token->mechListMIC);
+                       } else {
+                               /* RFC 2478 says we have an Octet String here,
+                                  but W2k sends something different... */
                                char *mechListMIC;
                                asn1_push_tag(asn1, ASN1_SEQUENCE(0));
                                asn1_push_tag(asn1, ASN1_CONTEXT(0));
@@ -97,7 +106,7 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
        return !asn1->has_error;
 }
 
-static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
+static bool write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
 {
        asn1_push_tag(asn1, ASN1_CONTEXT(0));
        asn1_push_tag(asn1, ASN1_SEQUENCE(0));
@@ -135,8 +144,22 @@ static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
        /* write mechListMIC */
        if (token->mechListMIC.data) {
                asn1_push_tag(asn1, ASN1_CONTEXT(3));
+#if 0
+               /* This is what RFC 2478 says ... */
                asn1_write_OctetString(asn1, token->mechListMIC.data,
                                       token->mechListMIC.length);
+#else
+               /* ... but unfortunately this is what Windows
+                  sends/expects */
+               asn1_push_tag(asn1, ASN1_SEQUENCE(0));
+               asn1_push_tag(asn1, ASN1_CONTEXT(0));
+               asn1_push_tag(asn1, ASN1_GENERAL_STRING);
+               asn1_write(asn1, token->mechListMIC.data,
+                          token->mechListMIC.length);
+               asn1_pop_tag(asn1);
+               asn1_pop_tag(asn1);
+               asn1_pop_tag(asn1);
+#endif         
                asn1_pop_tag(asn1);
        }
 
@@ -146,7 +169,7 @@ static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
        return !asn1->has_error;
 }
 
-static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
+static bool read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
 {
        ZERO_STRUCTP(token);
 
@@ -156,8 +179,6 @@ static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
        while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
                switch (asn1->data[asn1->ofs]) {
                case ASN1_CONTEXT(0):
-                       /* this is listed as being non-optional by RFC2478 but
-                          Windows doesn't always send it... */
                        asn1_start_tag(asn1, ASN1_CONTEXT(0));
                        asn1_start_tag(asn1, ASN1_ENUMERATED);
                        asn1_read_uint8(asn1, &token->negResult);
@@ -191,7 +212,7 @@ static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
        return !asn1->has_error;
 }
 
-static BOOL write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
+static bool write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
 {
        asn1_push_tag(asn1, ASN1_CONTEXT(1));
        asn1_push_tag(asn1, ASN1_SEQUENCE(0));
@@ -290,3 +311,36 @@ ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
        return ret;
 }
 
+bool free_spnego_data(SPNEGO_DATA *spnego)
+{
+       bool ret = True;
+
+       if (!spnego) goto out;
+
+       switch(spnego->type) {
+       case SPNEGO_NEG_TOKEN_INIT:
+               if (spnego->negTokenInit.mechTypes) {
+                       int i;
+                       for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) {
+                               free(CONST_DISCARD(char *,spnego->negTokenInit.mechTypes[i]));
+                       }
+                       free(spnego->negTokenInit.mechTypes);
+               }
+               data_blob_free(&spnego->negTokenInit.mechToken);
+               data_blob_free(&spnego->negTokenInit.mechListMIC);
+               break;
+       case SPNEGO_NEG_TOKEN_TARG:
+               if (spnego->negTokenTarg.supportedMech) {
+                       free(spnego->negTokenTarg.supportedMech);
+               }
+               data_blob_free(&spnego->negTokenTarg.responseToken);
+               data_blob_free(&spnego->negTokenTarg.mechListMIC);
+               break;
+       default:
+               ret = False;
+               break;
+       }
+       ZERO_STRUCTP(spnego);
+out:
+       return ret;
+}