LCOV - code coverage report
Current view: top level - source3/libsmb - clispnego.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 43 89 48.3 %
Date: 2021-09-23 10:06:22 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    simple kerberos5/SPNEGO routines
       4             :    Copyright (C) Andrew Tridgell 2001
       5             :    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
       6             :    Copyright (C) Luke Howard     2003
       7             :    Copyright (C) Jeremy Allison 2010
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "../libcli/auth/spnego.h"
      25             : #include "smb_krb5.h"
      26             : #include "../lib/util/asn1.h"
      27             : 
      28             : /*
      29             :   parse a negTokenInit packet giving a GUID, a list of supported
      30             :   OIDs (the mechanisms) and a principal name string 
      31             : */
      32         342 : bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
      33             :                                DATA_BLOB blob,
      34             :                                char *OIDs[ASN1_MAX_OIDS],
      35             :                                char **principal,
      36             :                                DATA_BLOB *secblob)
      37             : {
      38             :         int i;
      39         342 :         bool ret = false;
      40             :         ASN1_DATA *data;
      41             : 
      42        7182 :         for (i = 0; i < ASN1_MAX_OIDS; i++) {
      43        6840 :                 OIDs[i] = NULL;
      44             :         }
      45             : 
      46         342 :         if (principal) {
      47         342 :                 *principal = NULL;
      48             :         }
      49         342 :         if (secblob) {
      50           0 :                 *secblob = data_blob_null;
      51             :         }
      52             : 
      53         342 :         data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
      54         342 :         if (data == NULL) {
      55           0 :                 return false;
      56             :         }
      57             : 
      58         342 :         if (!asn1_load(data, blob)) goto err;
      59             : 
      60         342 :         if (!asn1_start_tag(data,ASN1_APPLICATION(0))) goto err;
      61             : 
      62         342 :         if (!asn1_check_OID(data,OID_SPNEGO)) goto err;
      63             : 
      64             :         /* negTokenInit  [0]  NegTokenInit */
      65         342 :         if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
      66         342 :         if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
      67             : 
      68             :         /* mechTypes [0] MechTypeList  OPTIONAL */
      69             : 
      70             :         /* Not really optional, we depend on this to decide
      71             :          * what mechanisms we have to work with. */
      72             : 
      73         342 :         if (!asn1_start_tag(data,ASN1_CONTEXT(0))) goto err;
      74         342 :         if (!asn1_start_tag(data,ASN1_SEQUENCE(0))) goto err;
      75        1368 :         for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
      76        1026 :                 if (!asn1_read_OID(data,ctx, &OIDs[i])) {
      77           0 :                         goto err;
      78             :                 }
      79        1026 :                 if (asn1_has_error(data)) {
      80           0 :                         goto err;
      81             :                 }
      82             :         }
      83         342 :         OIDs[i] = NULL;
      84         342 :         if (!asn1_end_tag(data)) goto err;
      85         342 :         if (!asn1_end_tag(data)) goto err;
      86             : 
      87             :         /*
      88             :           Win7 + Live Sign-in Assistant attaches a mechToken
      89             :           ASN1_CONTEXT(2) to the negTokenInit packet
      90             :           which breaks our negotiation if we just assume
      91             :           the next tag is ASN1_CONTEXT(3).
      92             :         */
      93             : 
      94         342 :         if (asn1_peek_tag(data, ASN1_CONTEXT(1))) {
      95             :                 uint8_t flags;
      96             : 
      97             :                 /* reqFlags [1] ContextFlags  OPTIONAL */
      98           0 :                 if (!asn1_start_tag(data, ASN1_CONTEXT(1))) goto err;
      99           0 :                 if (!asn1_start_tag(data, ASN1_BIT_STRING)) goto err;
     100           0 :                 while (asn1_tag_remaining(data) > 0) {
     101           0 :                         if (!asn1_read_uint8(data, &flags)) goto err;
     102             :                 }
     103           0 :                 if (!asn1_end_tag(data)) goto err;
     104           0 :                 if (!asn1_end_tag(data)) goto err;
     105             :         }
     106             : 
     107         342 :         if (asn1_peek_tag(data, ASN1_CONTEXT(2))) {
     108           0 :                 DATA_BLOB sblob = data_blob_null;
     109             :                 /* mechToken [2] OCTET STRING  OPTIONAL */
     110           0 :                 if (!asn1_start_tag(data, ASN1_CONTEXT(2))) goto err;
     111           0 :                 if (!asn1_read_OctetString(data, ctx, &sblob)) goto err;
     112           0 :                 if (!asn1_end_tag(data)) {
     113           0 :                         data_blob_free(&sblob);
     114           0 :                         goto err;
     115             :                 }
     116           0 :                 if (secblob) {
     117           0 :                         *secblob = sblob;
     118             :                 } else {
     119           0 :                         data_blob_free(&sblob);
     120             :                 }
     121             :         }
     122             : 
     123         342 :         if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
     124         342 :                 char *princ = NULL;
     125             :                 /* mechListMIC [3] OCTET STRING  OPTIONAL */
     126         342 :                 if (!asn1_start_tag(data, ASN1_CONTEXT(3))) goto err;
     127         342 :                 if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) goto err;
     128         342 :                 if (!asn1_start_tag(data, ASN1_CONTEXT(0))) goto err;
     129         342 :                 if (!asn1_read_GeneralString(data, ctx, &princ)) goto err;
     130         342 :                 if (!asn1_end_tag(data)) goto err;
     131         342 :                 if (!asn1_end_tag(data)) goto err;
     132         342 :                 if (!asn1_end_tag(data)) goto err;
     133         342 :                 if (principal) {
     134         342 :                         *principal = princ;
     135             :                 } else {
     136           0 :                         TALLOC_FREE(princ);
     137             :                 }
     138             :         }
     139             : 
     140         342 :         if (!asn1_end_tag(data)) goto err;
     141         342 :         if (!asn1_end_tag(data)) goto err;
     142             : 
     143         342 :         if (!asn1_end_tag(data)) goto err;
     144             : 
     145         342 :         ret = !asn1_has_error(data);
     146             : 
     147         342 :   err:
     148             : 
     149         342 :         if (asn1_has_error(data)) {
     150             :                 int j;
     151           0 :                 if (principal) {
     152           0 :                         TALLOC_FREE(*principal);
     153             :                 }
     154           0 :                 if (secblob) {
     155           0 :                         data_blob_free(secblob);
     156             :                 }
     157           0 :                 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
     158           0 :                         TALLOC_FREE(OIDs[j]);
     159             :                 }
     160             :         }
     161             : 
     162         342 :         asn1_free(data);
     163         342 :         return ret;
     164             : }
     165             : 
     166             : /*
     167             :   generate a krb5 GSS-API wrapper packet given a ticket
     168             : */
     169           0 : DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8_t tok_id[2])
     170             : {
     171             :         ASN1_DATA *data;
     172           0 :         DATA_BLOB ret = data_blob_null;
     173             : 
     174           0 :         data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
     175           0 :         if (data == NULL) {
     176           0 :                 return data_blob_null;
     177             :         }
     178             : 
     179           0 :         if (!asn1_push_tag(data, ASN1_APPLICATION(0))) goto err;
     180           0 :         if (!asn1_write_OID(data, OID_KERBEROS5)) goto err;
     181             : 
     182           0 :         if (!asn1_write(data, tok_id, 2)) goto err;
     183           0 :         if (!asn1_write(data, ticket.data, ticket.length)) goto err;
     184           0 :         if (!asn1_pop_tag(data)) goto err;
     185             : 
     186           0 :         if (!asn1_extract_blob(data, ctx, &ret)) {
     187           0 :                 goto err;
     188             :         }
     189             : 
     190           0 :         asn1_free(data);
     191           0 :         data = NULL;
     192             : 
     193           0 :   err:
     194             : 
     195           0 :         if (data != NULL) {
     196           0 :                 if (asn1_has_error(data)) {
     197           0 :                         DEBUG(1, ("Failed to build krb5 wrapper at offset %d\n",
     198             :                                   (int)asn1_current_ofs(data)));
     199             :                 }
     200             : 
     201           0 :                 asn1_free(data);
     202             :         }
     203             : 
     204           0 :         return ret;
     205             : }

Generated by: LCOV version 1.13