1 // Copyright 2012 Nexenta Systems, Inc. All rights reserved.
2 // Copyright (C) 2002 Microsoft Corporation
3 // All rights reserved.
4 //
5 // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
6 // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
7 // OR IMPLIED, INCLUDING BUT NOT LIMITED
8 // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
9 // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
10 //
11 // Date - 10/08/2002
12 // Author - Sanj Surati
13
14 /////////////////////////////////////////////////////////////
15 //
16 // SPNEGO.C
17 //
18 // SPNEGO Token Handler Source File
19 //
20 // Contains implementation of SPNEGO Token Handling API
21 // as defined in SPNEGO.H.
22 //
23 /////////////////////////////////////////////////////////////
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <memory.h>
29 #include "spnego.h"
30 #include "derparse.h"
31 #include "spnegoparse.h"
32
33 //
34 // Defined in DERPARSE.C
35 //
36
37 extern MECH_OID g_stcMechOIDList [];
38
39
40 /**********************************************************************/
41 /** **/
42 /** **/
43 /** **/
44 /** **/
45 /** SPNEGO Token Handler API implementation **/
46 /** **/
47 /** **/
48 /** **/
49 /** **/
50 /**********************************************************************/
51
52
53 /////////////////////////////////////////////////////////////////////////////
54 //
55 // Function:
56 // spnegoInitFromBinary
57 //
58 // Parameters:
59 // [in] pbTokenData - Binary Token Data
60 // [in] ulLength - Length of binary Token Data
61 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
62 //
63 // Returns:
64 // int Success - SPNEGO_E_SUCCESS
65 // Failure - SPNEGO API Error code
66 //
67 // Comments :
68 // Initializes a SPNEGO_TOKEN_HANDLE from the supplied
69 // binary data. Data is copied locally. Returned data structure
70 // must be freed by calling spnegoFreeData().
71 //
72 ////////////////////////////////////////////////////////////////////////////
73
spnegoInitFromBinary(unsigned char * pbTokenData,unsigned long ulLength,SPNEGO_TOKEN_HANDLE * phSpnegoToken)74 int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
75 {
76 int nReturn = SPNEGO_E_INVALID_PARAMETER;
77 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
78
79 // Pass off to a handler function that allows tighter control over how the token structure
80 // is handled. In this case, we want the token data copied and we want the associated buffer
81 // freed.
82 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA,
83 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, pbTokenData,
84 ulLength, ppSpnegoToken );
85
86 return nReturn;
87 }
88
89 /////////////////////////////////////////////////////////////////////////////
90 //
91 // Function:
92 // spnegoCreateNegTokenHint
93 //
94 // Parameters:
95 // [in] pMechTypeList - List of MechTypes (OIDs) to include
96 // [in] MechTypeCnt - Length of MechTypes array
97 // [in] pbPrincipal - Principal name for MechListMIC
98 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
99 //
100 // Returns:
101 // int Success - SPNEGO_E_SUCCESS
102 // Failure - SPNEGO API Error code
103 //
104 // Comments :
105 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type token
106 // from the supplied parameters. The token created is the "hint"
107 // used (for example) in the response to an SMB negotiate protocol.
108 // Returned data structure must be freed by calling spnegoFreeData().
109 //
110 // The "hint" tells the client what authentication methods this
111 // server supports (the ones in the MechTypeList). The Principal
112 // name historically was the server's own SPN, but recent versions
113 // of windows only supply: "not_defined_in_RFC4178@please_ignore"
114 // So if you want to be nice to your clients, provide the host SPN,
115 // otherwise provide the bogus SPN string like recent windows.
116 //
117 ////////////////////////////////////////////////////////////////////////////
118
spnegoCreateNegTokenHint(SPNEGO_MECH_OID * pMechTypeList,int MechTypeCnt,unsigned char * pbPrincipal,SPNEGO_TOKEN_HANDLE * phSpnegoToken)119 int spnegoCreateNegTokenHint( SPNEGO_MECH_OID *pMechTypeList, int MechTypeCnt,
120 unsigned char *pbPrincipal, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
121 {
122 int nReturn;
123 long nTokenLength = 0L;
124 long nInternalTokenLength = 0L;
125 unsigned long ulPrincipalLen;
126 unsigned char* pbMechListMIC;
127 unsigned long ulMechListMICLen;
128 unsigned char* pbTokenData = NULL;
129 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
130
131 if ( NULL == ppSpnegoToken || NULL == pbPrincipal )
132 return (SPNEGO_E_INVALID_PARAMETER);
133
134 /*
135 * Get the actual token size
136 */
137 ulPrincipalLen = strlen((char *)pbPrincipal);
138 ulMechListMICLen = ASNDerCalcElementLength( ulPrincipalLen, NULL );
139 nReturn = CalculateMinSpnegoInitTokenSize(
140 0, /* ulMechTokenLen */
141 ulMechListMICLen,
142 pMechTypeList,
143 MechTypeCnt,
144 0, /* nReqFlagsAvailable */
145 &nTokenLength,
146 &nInternalTokenLength );
147 if ( nReturn != SPNEGO_E_SUCCESS )
148 return (nReturn);
149
150 // Allocate a buffer to hold the data.
151 pbTokenData = calloc( 1, nTokenLength );
152
153 if ( NULL == pbTokenData )
154 return ( SPNEGO_E_OUT_OF_MEMORY );
155
156 /*
157 * Construct the MechListMIC
158 */
159 pbMechListMIC = pbTokenData + (nTokenLength - ulMechListMICLen);
160 (void) ASNDerWriteElement( pbMechListMIC, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
161 GENERALSTR, pbPrincipal, ulPrincipalLen );
162
163 // Now write the token
164 nReturn = CreateSpnegoInitToken(
165 pMechTypeList,
166 MechTypeCnt,
167 0, /* ContextFlags */
168 NULL, 0, /* MechToken, len */
169 pbMechListMIC,
170 ulMechListMICLen,
171 pbTokenData,
172 nTokenLength,
173 nInternalTokenLength );
174 if ( nReturn != SPNEGO_E_SUCCESS ) {
175 free( pbTokenData );
176 return (nReturn);
177 }
178
179 // This will copy our allocated pointer, and ensure that the sructure cleans
180 // up the data later
181 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
182 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
183 pbTokenData, nTokenLength, ppSpnegoToken );
184
185 // Cleanup on failure
186 if ( nReturn != SPNEGO_E_SUCCESS ) {
187 free( pbTokenData );
188 return (nReturn);
189 }
190
191 return (SPNEGO_E_SUCCESS);
192 }
193
194 /////////////////////////////////////////////////////////////////////////////
195 //
196 // Function:
197 // spnegoCreateNegTokenInit
198 //
199 // Parameters:
200 // [in] MechType - MechType to specify in MechTypeList element
201 // [in] ucContextFlags - Context Flags element value
202 // [in] pbMechToken - Pointer to binary MechToken Data
203 // [in] ulMechTokenLen - Length of MechToken Data
204 // [in] pbMechListMIC - Pointer to binary MechListMIC Data
205 // [in] ulMechListMICLen - Length of MechListMIC Data
206 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
207 //
208 // Returns:
209 // int Success - SPNEGO_E_SUCCESS
210 // Failure - SPNEGO API Error code
211 //
212 // Comments :
213 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type
214 // from the supplied parameters. ucContextFlags may be 0 or must be
215 // a valid flag combination. MechToken data can be NULL - if not, it
216 // must correspond to the MechType. MechListMIC can also be NULL.
217 // Returned data structure must be freed by calling spnegoFreeData().
218 //
219 ////////////////////////////////////////////////////////////////////////////
220
spnegoCreateNegTokenInit(SPNEGO_MECH_OID MechType,unsigned char ucContextFlags,unsigned char * pbMechToken,unsigned long ulMechTokenLen,unsigned char * pbMechListMIC,unsigned long ulMechListMICLen,SPNEGO_TOKEN_HANDLE * phSpnegoToken)221 int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
222 unsigned char ucContextFlags, unsigned char* pbMechToken,
223 unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
224 unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
225 {
226 int nReturn = SPNEGO_E_INVALID_PARAMETER;
227 long nTokenLength = 0L;
228 long nInternalTokenLength = 0L;
229 unsigned char* pbTokenData = NULL;
230 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
231
232 if ( NULL != ppSpnegoToken &&
233 IsValidMechOid( MechType ) &&
234 IsValidContextFlags( ucContextFlags ) )
235 {
236 // Get the actual token size
237
238 if ( ( nReturn = CalculateMinSpnegoInitTokenSize( ulMechTokenLen, ulMechListMICLen,
239 &MechType, 1, ( ucContextFlags != 0L ),
240 &nTokenLength, &nInternalTokenLength ) )
241 == SPNEGO_E_SUCCESS )
242 {
243 // Allocate a buffer to hold the data.
244 pbTokenData = calloc( 1, nTokenLength );
245
246 if ( NULL != pbTokenData )
247 {
248
249 // Now write the token
250 if ( ( nReturn = CreateSpnegoInitToken( &MechType, 1,
251 ucContextFlags, pbMechToken,
252 ulMechTokenLen, pbMechListMIC,
253 ulMechListMICLen, pbTokenData,
254 nTokenLength, nInternalTokenLength ) )
255 == SPNEGO_E_SUCCESS )
256 {
257
258 // This will copy our allocated pointer, and ensure that the sructure cleans
259 // up the data later
260 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
261 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
262 pbTokenData, nTokenLength, ppSpnegoToken );
263
264 }
265
266 // Cleanup on failure
267 if ( SPNEGO_E_SUCCESS != nReturn )
268 {
269 free( pbTokenData );
270 }
271
272 } // IF alloc succeeded
273 else
274 {
275 nReturn = SPNEGO_E_OUT_OF_MEMORY;
276 }
277
278 } // If calculated token size
279
280 } // IF Valid Parameters
281
282 return nReturn;
283 }
284
285 /////////////////////////////////////////////////////////////////////////////
286 //
287 // Function:
288 // spnegoCreateNegTokenTarg
289 //
290 // Parameters:
291 // [in] MechType - MechType to specify in supported MechType element
292 // [in] spnegoNegResult - NegResult value
293 // [in] pbMechToken - Pointer to response MechToken Data
294 // [in] ulMechTokenLen - Length of MechToken Data
295 // [in] pbMechListMIC - Pointer to binary MechListMIC Data
296 // [in] ulMechListMICLen - Length of MechListMIC Data
297 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
298 //
299 // Returns:
300 // int Success - SPNEGO_E_SUCCESS
301 // Failure - SPNEGO API Error code
302 //
303 // Comments :
304 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenTarg type
305 // from the supplied parameters. MechToken data can be NULL - if not,
306 // it must correspond to the MechType. MechListMIC can also be NULL.
307 // Returned data structure must be freed by calling spnegoFreeData().
308 //
309 ////////////////////////////////////////////////////////////////////////////
310
spnegoCreateNegTokenTarg(SPNEGO_MECH_OID MechType,SPNEGO_NEGRESULT spnegoNegResult,unsigned char * pbMechToken,unsigned long ulMechTokenLen,unsigned char * pbMechListMIC,unsigned long ulMechListMICLen,SPNEGO_TOKEN_HANDLE * phSpnegoToken)311 int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType,
312 SPNEGO_NEGRESULT spnegoNegResult, unsigned char* pbMechToken,
313 unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
314 unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
315 {
316 int nReturn = SPNEGO_E_INVALID_PARAMETER;
317 long nTokenLength = 0L;
318 long nInternalTokenLength = 0L;
319 unsigned char* pbTokenData = NULL;
320 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
321
322 //
323 // spnego_mech_oid_NotUsed and spnego_negresult_NotUsed
324 // are okay here, however a valid MechOid is required
325 // if spnego_negresult_success or spnego_negresult_incomplete
326 // is specified.
327 //
328
329 if ( NULL != ppSpnegoToken &&
330
331 ( IsValidMechOid( MechType ) ||
332 spnego_mech_oid_NotUsed == MechType ) &&
333
334 ( IsValidNegResult( spnegoNegResult ) ||
335 spnego_negresult_NotUsed == spnegoNegResult ) )
336 {
337
338 // Get the actual token size
339
340 if ( ( nReturn = CalculateMinSpnegoTargTokenSize( MechType, spnegoNegResult, ulMechTokenLen,
341 ulMechListMICLen, &nTokenLength,
342 &nInternalTokenLength ) )
343 == SPNEGO_E_SUCCESS )
344 {
345 // Allocate a buffer to hold the data.
346 pbTokenData = calloc( 1, nTokenLength );
347
348 if ( NULL != pbTokenData )
349 {
350
351 // Now write the token
352 if ( ( nReturn = CreateSpnegoTargToken( MechType,
353 spnegoNegResult, pbMechToken,
354 ulMechTokenLen, pbMechListMIC,
355 ulMechListMICLen, pbTokenData,
356 nTokenLength, nInternalTokenLength ) )
357 == SPNEGO_E_SUCCESS )
358 {
359
360 // This will copy our allocated pointer, and ensure that the sructure cleans
361 // up the data later
362 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
363 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
364 pbTokenData, nTokenLength, ppSpnegoToken );
365
366 }
367
368 // Cleanup on failure
369 if ( SPNEGO_E_SUCCESS != nReturn )
370 {
371 free( pbTokenData );
372 }
373
374 } // IF alloc succeeded
375 else
376 {
377 nReturn = SPNEGO_E_OUT_OF_MEMORY;
378 }
379
380 } // If calculated token size
381
382 } // IF Valid Parameters
383
384 return nReturn;
385 }
386
387 /////////////////////////////////////////////////////////////////////////////
388 //
389 // Function:
390 // spnegoTokenGetBinary
391 //
392 // Parameters:
393 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
394 // [out] pbTokenData - Buffer to copy token into
395 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
396 // with actual size used upon function return.
397 //
398 // Returns:
399 // int Success - SPNEGO_E_SUCCESS
400 // Failure - SPNEGO API Error code
401 //
402 // Comments :
403 // Copies binary SPNEGO token data from hSpnegoToken into the user
404 // supplied buffer. If pbTokenData is NULL, or the value in pulDataLen
405 // is too small, the function will return SPNEGO_E_BUFFER_TOO_SMALL and
406 // fill out pulDataLen with the minimum required buffer size.
407 //
408 ////////////////////////////////////////////////////////////////////////////
409
spnegoTokenGetBinary(SPNEGO_TOKEN_HANDLE hSpnegoToken,unsigned char * pbTokenData,unsigned long * pulDataLen)410 int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData,
411 unsigned long * pulDataLen )
412 {
413 int nReturn = SPNEGO_E_INVALID_PARAMETER;
414 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
415
416 // Check parameters - pbTokenData is optional
417 if ( IsValidSpnegoToken( pSpnegoToken ) &&
418 NULL != pulDataLen )
419 {
420
421 // Check for Buffer too small conditions
422 if ( NULL == pbTokenData ||
423 pSpnegoToken->ulBinaryDataLen > *pulDataLen )
424 {
425 *pulDataLen = pSpnegoToken->ulBinaryDataLen;
426 nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
427 }
428 else
429 {
430 memcpy( pbTokenData, pSpnegoToken->pbBinaryData, pSpnegoToken->ulBinaryDataLen );
431 *pulDataLen = pSpnegoToken->ulBinaryDataLen;
432 nReturn = SPNEGO_E_SUCCESS;
433 }
434
435 } // IF parameters OK
436
437 return nReturn;;
438 }
439
440 /////////////////////////////////////////////////////////////////////////////
441 //
442 // Function:
443 // spnegoFreeData
444 //
445 // Parameters:
446 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
447 //
448 // Returns:
449 // void
450 //
451 // Comments :
452 // Frees up resources consumed by hSpnegoToken. The supplied data
453 // pointer is invalidated by this function.
454 //
455 ////////////////////////////////////////////////////////////////////////////
456
spnegoFreeData(SPNEGO_TOKEN_HANDLE hSpnegoToken)457 void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken )
458 {
459 FreeSpnegoToken( (SPNEGO_TOKEN*) hSpnegoToken);
460 return;
461 }
462
463 /////////////////////////////////////////////////////////////////////////////
464 //
465 // Function:
466 // spnegoGetTokenType
467 //
468 // Parameters:
469 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
470 // [out] piTokenType - Filled out with token type value.
471 //
472 // Returns:
473 // int Success - SPNEGO_E_SUCCESS
474 // Failure - SPNEGO API Error code
475 //
476 // Comments :
477 // The function will analyze hSpnegoToken and return the appropriate
478 // type in piTokenType.
479 //
480 ////////////////////////////////////////////////////////////////////////////
481
spnegoGetTokenType(SPNEGO_TOKEN_HANDLE hSpnegoToken,int * piTokenType)482 int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken, int * piTokenType )
483 {
484 int nReturn = SPNEGO_E_INVALID_PARAMETER;
485 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
486
487 // Check parameters
488 if ( IsValidSpnegoToken( pSpnegoToken ) &&
489 NULL != piTokenType &&
490 pSpnegoToken)
491 {
492
493 // Check that the type in the structure makes sense
494 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ||
495 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
496 {
497 *piTokenType = pSpnegoToken->ucTokenType;
498 nReturn = SPNEGO_E_SUCCESS;
499 }
500
501 } // IF parameters OK
502
503 return nReturn;
504 }
505
506 /////////////////////////////////////////////////////////////////////////////
507 //
508 // Function:
509 // spnegoIsMechTypeAvailable
510 //
511 // Parameters:
512 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
513 // [in] MechOID - MechOID to search MechTypeList for
514 // [out] piMechTypeIndex - Filled out with index in MechTypeList
515 // element if MechOID is found.
516 //
517 // Returns:
518 // int Success - SPNEGO_E_SUCCESS
519 // Failure - SPNEGO API Error code
520 //
521 // Comments :
522 // hSpnegoToken must reference a token of type NegTokenInit. The
523 // function will search the MechTypeList element for an OID corresponding
524 // to the specified MechOID. If one is found, the index (0 based) will
525 // be passed into the piMechTypeIndex parameter.
526 //
527 ////////////////////////////////////////////////////////////////////////////
528
529 // Returns the Initial Mech Type in the MechList element in the NegInitToken.
spnegoIsMechTypeAvailable(SPNEGO_TOKEN_HANDLE hSpnegoToken,SPNEGO_MECH_OID MechOID,int * piMechTypeIndex)530 int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID MechOID, int * piMechTypeIndex )
531 {
532 int nReturn = SPNEGO_E_INVALID_PARAMETER;
533 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
534
535 // Check parameters
536 if ( IsValidSpnegoToken( pSpnegoToken ) &&
537 NULL != piMechTypeIndex &&
538 IsValidMechOid( MechOID ) &&
539 SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
540 {
541
542 // Check if MechList is available
543 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT].iElementPresent
544 == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
545 {
546 // Locate the MechOID in the list element
547 nReturn = FindMechOIDInMechList(
548 &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT],
549 MechOID, piMechTypeIndex );
550 }
551 else
552 {
553 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
554 }
555
556 } // IF parameters OK
557
558 return nReturn;;
559 }
560
561 /////////////////////////////////////////////////////////////////////////////
562 //
563 // Function:
564 // spnegoGetContextFlags
565 //
566 // Parameters:
567 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
568 // [out] pucContextFlags - Filled out with ContextFlags value.
569 //
570 // Returns:
571 // int Success - SPNEGO_E_SUCCESS
572 // Failure - SPNEGO API Error code
573 //
574 // Comments :
575 // hSpnegoToken must reference a token of type NegTokenInit. The
576 // function will copy data from the ContextFlags element into the
577 // location pucContextFlags points to. Note that the function will
578 // fail if the actual ContextFlags data appears invalid.
579 //
580 ////////////////////////////////////////////////////////////////////////////
581
spnegoGetContextFlags(SPNEGO_TOKEN_HANDLE hSpnegoToken,unsigned char * pucContextFlags)582 int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pucContextFlags )
583 {
584 int nReturn = SPNEGO_E_INVALID_PARAMETER;
585 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
586
587 // Check parameters
588 if ( IsValidSpnegoToken( pSpnegoToken ) &&
589 NULL != pucContextFlags &&
590 SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
591 {
592
593 // Check if ContextFlags is available
594 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].iElementPresent
595 == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
596 {
597 // The length should be two, the value should show a 1 bit difference in the difference byte, and
598 // the value must be valid
599 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].nDatalength == SPNEGO_NEGINIT_MAXLEN_REQFLAGS &&
600 pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[0] == SPNEGO_NEGINIT_REQFLAGS_BITDIFF &&
601 IsValidContextFlags( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1] ) )
602 {
603 *pucContextFlags = pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1];
604 nReturn = SPNEGO_E_SUCCESS;
605 }
606 else
607 {
608 nReturn = SPNEGO_E_INVALID_ELEMENT;
609 }
610
611 }
612 else
613 {
614 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
615 }
616
617 } // IF parameters OK
618
619 return nReturn;;
620 }
621
622 /////////////////////////////////////////////////////////////////////////////
623 //
624 // Function:
625 // spnegoGetNegotiationResult
626 //
627 // Parameters:
628 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
629 // [out] pnegResult - Filled out with NegResult value.
630 //
631 // Returns:
632 // int Success - SPNEGO_E_SUCCESS
633 // Failure - SPNEGO API Error code
634 //
635 // Comments :
636 // hSpnegoToken must reference a token of type NegTokenTarg. The
637 // function will copy data from the NegResult element into the
638 // location pointed to by pnegResult. Note that the function will
639 // fail if the actual NegResult data appears invalid.
640 //
641 ////////////////////////////////////////////////////////////////////////////
642
spnegoGetNegotiationResult(SPNEGO_TOKEN_HANDLE hSpnegoToken,SPNEGO_NEGRESULT * pnegResult)643 int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_NEGRESULT* pnegResult )
644 {
645 int nReturn = SPNEGO_E_INVALID_PARAMETER;
646 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
647
648 // Check parameters
649 if ( IsValidSpnegoToken( pSpnegoToken ) &&
650 NULL != pnegResult &&
651 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
652 {
653
654 // Check if NegResult is available
655 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].iElementPresent
656 == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
657 {
658 // Must be 1 byte long and a valid value
659 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].nDatalength == SPNEGO_NEGTARG_MAXLEN_NEGRESULT &&
660 IsValidNegResult( *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData ) )
661 {
662 *pnegResult = *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData;
663 nReturn = SPNEGO_E_SUCCESS;
664 }
665 else
666 {
667 nReturn = SPNEGO_E_INVALID_ELEMENT;
668 }
669 }
670 else
671 {
672 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
673 }
674
675 } // IF parameters OK
676
677 return nReturn;;
678 }
679
680 /////////////////////////////////////////////////////////////////////////////
681 //
682 // Function:
683 // spnegoGetSupportedMechType
684 //
685 // Parameters:
686 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
687 // [out] pMechOID - Filled out with Supported MechType value.
688 //
689 // Returns:
690 // int Success - SPNEGO_E_SUCCESS
691 // Failure - SPNEGO API Error code
692 //
693 // Comments :
694 // hSpnegoToken must reference a token of type NegTokenTarg. The
695 // function will check the Supported MechType element, and if it
696 // corresponds to a supported MechType ( spnego_mech_oid_Kerberos_V5_Legacy
697 // or spnego_mech_oid_Kerberos_V5 ), will set the location pointed
698 // to by pMechOID equal to the appropriate value.
699 //
700 ////////////////////////////////////////////////////////////////////////////
701
spnegoGetSupportedMechType(SPNEGO_TOKEN_HANDLE hSpnegoToken,SPNEGO_MECH_OID * pMechOID)702 int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID* pMechOID )
703 {
704 int nReturn = SPNEGO_E_INVALID_PARAMETER;
705 int nCtr = 0L;
706 long nLength = 0L;
707 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
708
709 // Check parameters
710 if ( IsValidSpnegoToken( pSpnegoToken ) &&
711 NULL != pMechOID &&
712 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
713 {
714
715 // Check if MechList is available
716 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].iElementPresent
717 == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
718 {
719
720 for ( nCtr = 0;
721 nReturn != SPNEGO_E_SUCCESS &&
722 g_stcMechOIDList[nCtr].eMechanismOID != spnego_mech_oid_NotUsed;
723 nCtr++ )
724 {
725
726 if ( ( nReturn = ASNDerCheckOID(
727 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].pbData,
728 nCtr,
729 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].nDatalength,
730 &nLength ) ) == SPNEGO_E_SUCCESS )
731 {
732 *pMechOID = nCtr;
733 }
734
735 } // For enum MechOIDs
736
737
738 }
739 else
740 {
741 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
742 }
743
744 } // IF parameters OK
745
746 return nReturn;;
747 }
748
749 /////////////////////////////////////////////////////////////////////////////
750 //
751 // Function:
752 // spnegoTokenGetMechToken
753 //
754 // Parameters:
755 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
756 // [out] pbTokenData - Buffer to copy MechToken into
757 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
758 // with actual size used upon function return.
759 //
760 // Returns:
761 // int Success - SPNEGO_E_SUCCESS
762 // Failure - SPNEGO API Error code
763 //
764 // Comments :
765 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
766 // The function will copy the MechToken (the initial MechToken if
767 // NegTokenInit, the response MechToken if NegTokenTarg) from the
768 // underlying token into the buffer pointed to by pbTokenData. If
769 // pbTokenData is NULL, or the value in pulDataLen is too small, the
770 // function will return SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen
771 // with the minimum required buffer size. The token can then be passed
772 // to a GSS-API function for processing.
773 //
774 ////////////////////////////////////////////////////////////////////////////
775
spnegoGetMechToken(SPNEGO_TOKEN_HANDLE hSpnegoToken,unsigned char * pbTokenData,unsigned long * pulDataLen)776 int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, unsigned long* pulDataLen )
777 {
778 int nReturn = SPNEGO_E_INVALID_PARAMETER;
779 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
780 SPNEGO_ELEMENT* pSpnegoElement = NULL;
781
782 // Check parameters
783 if ( IsValidSpnegoToken( pSpnegoToken ) &&
784 NULL != pulDataLen )
785 {
786
787 // Point at the proper Element
788 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
789 {
790 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTOKEN_ELEMENT];
791 }
792 else
793 {
794 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_RESPTOKEN_ELEMENT];
795 }
796
797 // Check if MechType is available
798 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent )
799 {
800 // Check for Buffer too small conditions
801 if ( NULL == pbTokenData ||
802 pSpnegoElement->nDatalength > *pulDataLen )
803 {
804 *pulDataLen = pSpnegoElement->nDatalength;
805 nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
806 }
807 else
808 {
809 // Copy Memory
810 memcpy( pbTokenData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
811 *pulDataLen = pSpnegoElement->nDatalength;
812 nReturn = SPNEGO_E_SUCCESS;
813 }
814 }
815 else
816 {
817 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
818 }
819
820 } // IF parameters OK
821
822 return nReturn;;
823 }
824
825 /////////////////////////////////////////////////////////////////////////////
826 //
827 // Function:
828 // spnegoTokenGetMechListMIC
829 //
830 // Parameters:
831 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
832 // [out] pbTokenData - Buffer to copy MechListMIC data into
833 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
834 // with actual size used upon function return.
835 //
836 // Returns:
837 // int Success - SPNEGO_E_SUCCESS
838 // Failure - SPNEGO API Error code
839 //
840 // Comments :
841 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
842 // The function will copy the MechListMIC data from the underlying token
843 // into the buffer pointed to by pbTokenData. If pbTokenData is NULL,
844 // or the value in pulDataLen is too small, the function will return
845 // SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen with the minimum
846 // required buffer size.
847 //
848 ////////////////////////////////////////////////////////////////////////////
849
spnegoGetMechListMIC(SPNEGO_TOKEN_HANDLE hSpnegoToken,unsigned char * pbMICData,unsigned long * pulDataLen)850 int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbMICData, unsigned long* pulDataLen )
851 {
852 int nReturn = SPNEGO_E_INVALID_PARAMETER;
853 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
854 SPNEGO_ELEMENT* pSpnegoElement = NULL;
855
856 // Check parameters
857 if ( IsValidSpnegoToken( pSpnegoToken ) &&
858 NULL != pulDataLen )
859 {
860
861 // Point at the proper Element
862 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
863 {
864 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHLISTMIC_ELEMENT];
865 }
866 else
867 {
868 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_MECHLISTMIC_ELEMENT];
869 }
870
871 // Check if MechType is available
872 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent )
873 {
874 // Check for Buffer too small conditions
875 if ( NULL == pbMICData ||
876 pSpnegoElement->nDatalength > *pulDataLen )
877 {
878 *pulDataLen = pSpnegoElement->nDatalength;
879 nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
880 }
881 else
882 {
883 // Copy Memory
884 memcpy( pbMICData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
885 *pulDataLen = pSpnegoElement->nDatalength;
886 nReturn = SPNEGO_E_SUCCESS;
887 }
888 }
889 else
890 {
891 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
892 }
893
894 } // IF parameters OK
895
896 return nReturn;;
897 }
898
899