github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/internal/sasl/sasl_windows.c (about)

     1  #include "sasl_windows.h"
     2  
     3  static const LPSTR SSPI_PACKAGE_NAME = "kerberos";
     4  
     5  SECURITY_STATUS SEC_ENTRY sspi_acquire_credentials_handle(CredHandle *cred_handle, char *username, char *password, char *domain)
     6  {
     7  	SEC_WINNT_AUTH_IDENTITY auth_identity;
     8  	SECURITY_INTEGER ignored;
     9  
    10  	auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
    11  	auth_identity.User = (LPSTR) username;
    12  	auth_identity.UserLength = strlen(username);
    13  	auth_identity.Password = NULL;
    14  	auth_identity.PasswordLength = 0;
    15  	if(password){
    16  		auth_identity.Password = (LPSTR) password;
    17  		auth_identity.PasswordLength = strlen(password);
    18  	}
    19  	auth_identity.Domain = (LPSTR) domain;
    20  	auth_identity.DomainLength = strlen(domain);
    21  	return call_sspi_acquire_credentials_handle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_identity, NULL, NULL, cred_handle, &ignored);
    22  }
    23  
    24  int sspi_step(CredHandle *cred_handle, int has_context, CtxtHandle *context, PVOID buffer, ULONG buffer_length, PVOID *out_buffer, ULONG *out_buffer_length,  char *target)
    25  {
    26  	SecBufferDesc inbuf;
    27  	SecBuffer in_bufs[1];
    28  	SecBufferDesc outbuf;
    29  	SecBuffer out_bufs[1];
    30  
    31  	if (has_context > 0) {
    32  		// If we already have a context, we now have data to send.
    33  		// Put this data in an inbuf.
    34  		inbuf.ulVersion = SECBUFFER_VERSION;
    35  		inbuf.cBuffers = 1;
    36  		inbuf.pBuffers = in_bufs;
    37  		in_bufs[0].pvBuffer = buffer;
    38  		in_bufs[0].cbBuffer = buffer_length;
    39  		in_bufs[0].BufferType = SECBUFFER_TOKEN;
    40  	}
    41  
    42  	outbuf.ulVersion = SECBUFFER_VERSION;
    43  	outbuf.cBuffers = 1;
    44  	outbuf.pBuffers = out_bufs;
    45  	out_bufs[0].pvBuffer = NULL;
    46  	out_bufs[0].cbBuffer = 0;
    47  	out_bufs[0].BufferType = SECBUFFER_TOKEN;
    48  
    49  	ULONG context_attr = 0;
    50  
    51  	int ret = call_sspi_initialize_security_context(cred_handle,
    52  	          has_context > 0 ? context : NULL,
    53  	          (LPSTR) target,
    54  	          ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MUTUAL_AUTH,
    55  	          0,
    56  	          SECURITY_NETWORK_DREP,
    57  	          has_context > 0 ? &inbuf : NULL,
    58  	          0,
    59  	          context,
    60  	          &outbuf,
    61  	          &context_attr,
    62  	          NULL);
    63  
    64  	*out_buffer = malloc(out_bufs[0].cbBuffer);
    65  	*out_buffer_length = out_bufs[0].cbBuffer;
    66  	memcpy(*out_buffer, out_bufs[0].pvBuffer, *out_buffer_length);
    67  
    68  	return ret;
    69  }
    70  
    71  int sspi_send_client_authz_id(CtxtHandle *context, PVOID *buffer, ULONG *buffer_length, char *user_plus_realm)
    72  {
    73  	SecPkgContext_Sizes sizes;
    74  	SECURITY_STATUS status = call_sspi_query_context_attributes(context, SECPKG_ATTR_SIZES, &sizes);
    75  
    76  	if (status != SEC_E_OK) {
    77  		return status;
    78  	}
    79  
    80  	size_t user_plus_realm_length = strlen(user_plus_realm);
    81  	int msgSize = 4 + user_plus_realm_length;
    82  	char *msg = malloc((sizes.cbSecurityTrailer + msgSize + sizes.cbBlockSize) * sizeof(char));
    83  	msg[sizes.cbSecurityTrailer + 0] = 1;
    84  	msg[sizes.cbSecurityTrailer + 1] = 0;
    85  	msg[sizes.cbSecurityTrailer + 2] = 0;
    86  	msg[sizes.cbSecurityTrailer + 3] = 0;
    87  	memcpy(&msg[sizes.cbSecurityTrailer + 4], user_plus_realm, user_plus_realm_length);
    88  
    89  	SecBuffer wrapBufs[3];
    90  	SecBufferDesc wrapBufDesc;
    91  	wrapBufDesc.cBuffers = 3;
    92  	wrapBufDesc.pBuffers = wrapBufs;
    93  	wrapBufDesc.ulVersion = SECBUFFER_VERSION;
    94  
    95  	wrapBufs[0].cbBuffer = sizes.cbSecurityTrailer;
    96  	wrapBufs[0].BufferType = SECBUFFER_TOKEN;
    97  	wrapBufs[0].pvBuffer = msg;
    98  
    99  	wrapBufs[1].cbBuffer = msgSize;
   100  	wrapBufs[1].BufferType = SECBUFFER_DATA;
   101  	wrapBufs[1].pvBuffer = msg + sizes.cbSecurityTrailer;
   102  
   103  	wrapBufs[2].cbBuffer = sizes.cbBlockSize;
   104  	wrapBufs[2].BufferType = SECBUFFER_PADDING;
   105  	wrapBufs[2].pvBuffer = msg + sizes.cbSecurityTrailer + msgSize;
   106  
   107  	status = call_sspi_encrypt_message(context, SECQOP_WRAP_NO_ENCRYPT, &wrapBufDesc, 0);
   108  	if (status != SEC_E_OK) {
   109  		free(msg);
   110  		return status;
   111  	}
   112  
   113  	*buffer_length = wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer + wrapBufs[2].cbBuffer;
   114  	*buffer = malloc(*buffer_length);
   115  
   116  	memcpy(*buffer, wrapBufs[0].pvBuffer, wrapBufs[0].cbBuffer);
   117  	memcpy(*buffer + wrapBufs[0].cbBuffer, wrapBufs[1].pvBuffer, wrapBufs[1].cbBuffer);
   118  	memcpy(*buffer + wrapBufs[0].cbBuffer + wrapBufs[1].cbBuffer, wrapBufs[2].pvBuffer, wrapBufs[2].cbBuffer);
   119  
   120  	free(msg);
   121  	return SEC_E_OK;
   122  }