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