Imported Upstream version 6.6.0.144

Former-commit-id: 335a70f3c58a7479968dcaae1d3412c2da9f9a3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-10-25 09:01:16 +00:00
parent 85bcceff8c
commit 790c4870fc
245 changed files with 629 additions and 257 deletions

View File

@@ -97,6 +97,7 @@ BEGIN_EXTERN_C
typedef int errno_t;
#ifndef HAVE_MEMCPY_S
inline static errno_t memcpy_s(void* dst, size_t sizeInBytes, const void* src, size_t count)
{
if (count > 0)
@@ -124,5 +125,6 @@ inline static errno_t memcpy_s(void* dst, size_t sizeInBytes, const void* src, s
return 0;
}
#endif
END_EXTERN_C

View File

@@ -816,6 +816,7 @@ static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, struct I
return 1;
}
#ifdef IPV6_PKTINFO
static int32_t GetIPv6PacketInformation(struct cmsghdr* controlMessage, struct IPPacketInformation* packetInfo)
{
assert(controlMessage != NULL);
@@ -834,6 +835,7 @@ static int32_t GetIPv6PacketInformation(struct cmsghdr* controlMessage, struct I
return 1;
}
#endif
static struct cmsghdr* GET_CMSG_NXTHDR(struct msghdr* mhdr, struct cmsghdr* cmsg)
{
@@ -1474,9 +1476,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO
*optName = SO_DEBUG;
return true;
#ifdef SO_ACCEPTCONN
case SocketOptionName_SO_ACCEPTCONN:
*optName = SO_ACCEPTCONN;
return true;
#endif
case SocketOptionName_SO_REUSEADDR:
*optName = SO_REUSEADDR;
@@ -1638,9 +1642,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO
// case SocketOptionName_SO_IPV6_PROTECTION_LEVEL:
#ifdef IPV6_V6ONLY
case SocketOptionName_SO_IPV6_V6ONLY:
*optName = IPV6_V6ONLY;
return true;
#endif
#ifdef IPV6_RECVPKTINFO
case SocketOptionName_SO_IP_PKTINFO:
@@ -1901,9 +1907,11 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palProtocolType, int* pl
*platformProtocolType = IPPROTO_UDP;
return true;
#ifdef IPPROTO_ICMPV6
case ProtocolType_PT_ICMPV6:
*platformProtocolType = IPPROTO_ICMPV6;
return true;
#endif
default:
*platformProtocolType = (int)palProtocolType;

View File

@@ -111,7 +111,7 @@ static uint32_t NetSecurityNative_DisplayStatus(uint32_t* minorStatus,
assert(minorStatus != NULL);
assert(outBuffer != NULL);
uint32_t messageContext;
uint32_t messageContext = 0; // Must initialize to 0 before calling gss_display_status.
GssBuffer gssBuffer = {.length = 0, .value = NULL};
uint32_t majorStatus =
gss_display_status(minorStatus, statusValue, statusType, GSS_C_NO_OID, &messageContext, &gssBuffer);
@@ -154,19 +154,36 @@ uint32_t NetSecurityNative_ImportPrincipalName(uint32_t* minorStatus,
assert(outputName != NULL);
assert(*outputName == NULL);
gss_OID nameType;
if (strchr(inputName, '/') != NULL)
// Principal name will usually be in the form SERVICE/HOST. But SPNEGO protocol prefers
// GSS_C_NT_HOSTBASED_SERVICE format. That format uses '@' separator instead of '/' between
// service name and host name. So convert input string into that format.
char* ptrSlash = memchr(inputName, '/', inputNameLen);
char* inputNameCopy = NULL;
if (ptrSlash != NULL)
{
nameType = GSS_KRB5_NT_PRINCIPAL_NAME;
}
else
{
nameType = GSS_C_NT_HOSTBASED_SERVICE;
inputNameCopy = (char*) malloc(inputNameLen);
if (inputNameCopy != NULL)
{
memcpy(inputNameCopy, inputName, inputNameLen);
inputNameCopy[ptrSlash - inputName] = '@';
inputName = inputNameCopy;
}
else
{
*minorStatus = 0;
return GSS_S_BAD_NAME;
}
}
GssBuffer inputNameBuffer = {.length = inputNameLen, .value = inputName};
return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
uint32_t result = gss_import_name(minorStatus, &inputNameBuffer, GSS_C_NT_HOSTBASED_SERVICE, outputName);
if (inputNameCopy != NULL)
{
free(inputNameCopy);
}
return result;
}
uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
@@ -180,6 +197,35 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed)
{
return NetSecurityNative_InitSecContextEx(minorStatus,
claimantCredHandle,
contextHandle,
isNtlm,
NULL,
0,
targetName,
reqFlags,
inputBytes,
inputLength,
outBuffer,
retFlags,
isNtlmUsed);
}
uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus,
GssCredId* claimantCredHandle,
GssCtxId** contextHandle,
uint32_t isNtlm,
void* cbt,
int32_t cbtSize,
GssName* targetName,
uint32_t reqFlags,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
@@ -189,12 +235,13 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
assert(outBuffer != NULL);
assert(retFlags != NULL);
assert(isNtlmUsed != NULL);
assert(inputBytes != NULL || inputLength == 0);
assert(cbt != NULL || cbtSize == 0);
// Note: claimantCredHandle can be null
// Note: *contextHandle is null only in the first call and non-null in the subsequent calls
#if HAVE_GSS_SPNEGO_MECHANISM
gss_OID krbMech = GSS_KRB5_MECHANISM;
gss_OID desiredMech;
if (isNtlm)
{
@@ -204,9 +251,8 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
{
desiredMech = GSS_SPNEGO_MECHANISM;
}
gss_OID krbMech = GSS_KRB5_MECHANISM;
#else
gss_OID krbMech = (gss_OID)(unsigned long)gss_mech_krb5;
gss_OID_desc gss_mech_OID_desc;
if (isNtlm)
{
@@ -218,14 +264,20 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
}
gss_OID desiredMech = &gss_mech_OID_desc;
gss_OID krbMech = gss_mech_krb5;
#endif
*isNtlmUsed = 1;
GssBuffer inputToken = {.length = inputLength, .value = inputBytes};
GssBuffer gssBuffer = {.length = 0, .value = NULL};
gss_OID_desc* outmech;
struct gss_channel_bindings_struct gssCbt;
if (cbt != NULL)
{
memset(&gssCbt, 0, sizeof(struct gss_channel_bindings_struct));
gssCbt.application_data.length = (size_t)cbtSize;
gssCbt.application_data.value = cbt;
}
uint32_t majorStatus = gss_init_sec_context(minorStatus,
claimantCredHandle,
contextHandle,
@@ -233,18 +285,14 @@ uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
desiredMech,
reqFlags,
0,
GSS_C_NO_CHANNEL_BINDINGS,
(cbt != NULL) ? &gssCbt : GSS_C_NO_CHANNEL_BINDINGS,
&inputToken,
&outmech,
&gssBuffer,
retFlags,
NULL);
// Outmech can be null when gssntlmssp lib uses NTLM mechanism
if (outmech != NULL && gss_oid_equal(outmech, krbMech) != 0)
{
*isNtlmUsed = 0;
}
*isNtlmUsed = (isNtlm || majorStatus != GSS_S_COMPLETE || gss_oid_equal(outmech, krbMech) == 0) ? 1 : 0;
NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
return majorStatus;
@@ -254,7 +302,8 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
GssCtxId** contextHandle,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer)
PAL_GssBuffer* outBuffer,
uint32_t* retFlags)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
@@ -273,7 +322,7 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
NULL,
NULL,
&gssBuffer,
0,
retFlags,
NULL,
NULL);
@@ -281,6 +330,44 @@ uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
return majorStatus;
}
uint32_t NetSecurityNative_GetUser(uint32_t* minorStatus,
GssCtxId* contextHandle,
PAL_GssBuffer* outBuffer)
{
assert(minorStatus != NULL);
assert(contextHandle != NULL);
assert(outBuffer != NULL);
gss_name_t srcName = GSS_C_NO_NAME;
uint32_t majorStatus = gss_inquire_context(minorStatus,
contextHandle,
&srcName,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if (majorStatus == GSS_S_COMPLETE)
{
GssBuffer gssBuffer = {.length = 0, .value = NULL};
majorStatus = gss_display_name(minorStatus, srcName, &gssBuffer, NULL);
if (majorStatus == GSS_S_COMPLETE)
{
NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
}
}
if (srcName != NULL)
{
majorStatus = gss_release_name(minorStatus, &srcName);
}
return majorStatus;
}
uint32_t NetSecurityNative_ReleaseCred(uint32_t* minorStatus, GssCredId** credHandle)
{
assert(minorStatus != NULL);
@@ -416,4 +503,37 @@ uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorStatus,
{
return NetSecurityNative_AcquireCredWithPassword(
minorStatus, isNtlm, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle);
}
uint32_t NetSecurityNative_IsNtlmInstalled()
{
#if HAVE_GSS_SPNEGO_MECHANISM
gss_OID ntlmOid = GSS_NTLM_MECHANISM;
#else
gss_OID ntlmOid = &gss_mech_ntlm_OID_desc;
#endif
uint32_t majorStatus;
uint32_t minorStatus;
gss_OID_set mechSet;
gss_OID_desc oid;
uint32_t foundNtlm = 0;
majorStatus = gss_indicate_mechs(&minorStatus, &mechSet);
if (majorStatus == GSS_S_COMPLETE)
{
for (size_t i = 0; i < mechSet->count; i++)
{
oid = mechSet->elements[i];
if ((oid.length == ntlmOid->length) && (memcmp(oid.elements, ntlmOid->elements, oid.length) == 0))
{
foundNtlm = 1;
break;
}
}
gss_release_oid_set(&minorStatus, &mechSet);
}
return foundNtlm;
}

View File

@@ -115,6 +115,20 @@ DLLEXPORT uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
uint32_t* retFlags,
int32_t* isNtlmUsed);
DLLEXPORT uint32_t NetSecurityNative_InitSecContextEx(uint32_t* minorStatus,
GssCredId* claimantCredHandle,
GssCtxId** contextHandle,
uint32_t isNtlm,
void* cbt,
int32_t cbtSize,
GssName* targetName,
uint32_t reqFlags,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer,
uint32_t* retFlags,
int32_t* isNtlmUsed);
/*
Shims the gss_accept_sec_context method.
*/
@@ -122,7 +136,8 @@ DLLEXPORT uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
GssCtxId** contextHandle,
uint8_t* inputBytes,
uint32_t inputLength,
PAL_GssBuffer* outBuffer);
PAL_GssBuffer* outBuffer,
uint32_t* retFlags);
/*
@@ -159,4 +174,16 @@ DLLEXPORT uint32_t NetSecurityNative_InitiateCredWithPassword(uint32_t* minorSta
GssName* desiredName,
char* password,
uint32_t passwdLen,
GssCredId** outputCredHandle);
GssCredId** outputCredHandle);
/*
Shims the gss_indicate_mechs method to detect if NTLM mech is installed.
*/
DLLEXPORT uint32_t NetSecurityNative_IsNtlmInstalled(void);
/*
Shims gss_inquire_context and gss_display_name to get the remote user principal name.
*/
DLLEXPORT uint32_t NetSecurityNative_GetUser(uint32_t* minorStatus,
GssCtxId* contextHandle,
PAL_GssBuffer* outBuffer);