diff --git a/libtirpc/src/auth_none.c b/libtirpc/src/auth_none.c index fc5654e..5bfa48a 100644 --- a/libtirpc/src/auth_none.c +++ b/libtirpc/src/auth_none.c @@ -156,6 +156,12 @@ authnone_destroy(AUTH *client) { } +static bool_t +authnone_wrap(AUTH *auth, XDR *xdrs, xdrproc_t func, caddr_t args, u_int seq) +{ + return ((*func)(xdrs, args)); +} + static struct auth_ops * authnone_ops() { @@ -171,6 +177,8 @@ authnone_ops() ops.ah_validate = authnone_validate; ops.ah_refresh = authnone_refresh; ops.ah_destroy = authnone_destroy; + ops.ah_wrap = authnone_wrap; + ops.ah_unwrap = authnone_wrap; } mutex_unlock(&ops_lock); return (&ops); diff --git a/libtirpc/src/auth_sspi.c b/libtirpc/src/auth_sspi.c index d618199..507d5a6 100644 --- a/libtirpc/src/auth_sspi.c +++ b/libtirpc/src/auth_sspi.c @@ -324,7 +324,7 @@ authsspi_validate(AUTH *auth, struct opaque_auth *verf, u_int seq) #else maj_stat = sspi_verify_mic(&gd->ctx, cur_seq, &signbuf, &checksum, &qop_state); #endif - if (maj_stat != SEC_E_OK || qop_state != gd->sec->qop) { + if (maj_stat != SEC_E_OK) { log_debug("authsspi_validate: VerifySignature failed with %x", maj_stat); if (maj_stat == SEC_E_NO_AUTHENTICATING_AUTHORITY) { gd->established = FALSE; @@ -373,7 +373,10 @@ authsspi_refresh(AUTH *auth, void *tmp) print_rpc_gss_sec(gd->sec); - for (i=0;;i++) { + if (gd->sec->svc == RPCSEC_SSPI_SVC_PRIVACY) + flags |= ISC_REQ_CONFIDENTIALITY; + + for (i=0;;i++) { /* print the token we just received */ if (recv_tokenp != SSPI_C_NO_BUFFER) { log_debug("The token we just received (length %d):", @@ -498,7 +501,7 @@ authsspi_refresh(AUTH *auth, void *tmp) #else maj_stat = sspi_verify_mic(&gd->ctx, 0, &bufin, &gd->gc_wire_verf, &qop_state); #endif - if (maj_stat != SEC_E_OK || qop_state != gd->sec->qop) { + if (maj_stat != SEC_E_OK) { log_debug("authgss_refresh: sspi_verify_mic failed with %x", maj_stat); if (maj_stat == SEC_E_NO_AUTHENTICATING_AUTHORITY) { gd->established = FALSE; @@ -623,7 +626,7 @@ authsspi_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) } bool_t -authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) +authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, u_int seq) { struct rpc_sspi_data *gd; @@ -636,7 +639,7 @@ authsspi_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) } return (xdr_rpc_sspi_data(xdrs, xdr_func, xdr_ptr, &gd->ctx, gd->sec->qop, - gd->sec->svc, gd->gc.gc_seq)); + gd->sec->svc, seq)); } uint32_t sspi_get_mic(PCtxtHandle ctx, u_int qop, u_int seq, @@ -720,6 +723,98 @@ uint32_t sspi_import_name(sspi_buffer_desc *name_in, sspi_name_t *name_out) return SEC_E_OK; } + +uint32_t sspi_wrap(PCtxtHandle ctx, u_int seq, sspi_buffer_desc *bufin, + sspi_buffer_desc *bufout, u_int *conf_state) +{ + uint32_t maj_stat; + SecBufferDesc BuffDesc; + SecBuffer SecBuff[3]; + ULONG ulQop = 0; + SecPkgContext_Sizes ContextSizes; + PBYTE p; + + maj_stat = QueryContextAttributes(ctx, SECPKG_ATTR_SIZES, + &ContextSizes); + if (maj_stat != SEC_E_OK) + goto out; + + BuffDesc.ulVersion = 0; + BuffDesc.cBuffers = 3; + BuffDesc.pBuffers = SecBuff; + + SecBuff[0].cbBuffer = ContextSizes.cbSecurityTrailer; + SecBuff[0].BufferType = SECBUFFER_TOKEN; + SecBuff[0].pvBuffer = malloc(ContextSizes.cbSecurityTrailer); + + SecBuff[1].cbBuffer = bufin->length; + SecBuff[1].BufferType = SECBUFFER_DATA; + SecBuff[1].pvBuffer = bufin->value; + log_hexdump(0, "plaintext:", bufin->value, bufin->length, 0); + + SecBuff[2].cbBuffer = ContextSizes.cbBlockSize; + SecBuff[2].BufferType = SECBUFFER_PADDING; + SecBuff[2].pvBuffer = malloc(ContextSizes.cbBlockSize); + + maj_stat = EncryptMessage(ctx, ulQop, &BuffDesc, 0); + if (maj_stat != SEC_E_OK) + goto out_free; + + bufout->length = SecBuff[0].cbBuffer + SecBuff[1].cbBuffer + SecBuff[2].cbBuffer; + p = bufout->value = malloc(bufout->length); + memcpy(p, SecBuff[0].pvBuffer, SecBuff[0].cbBuffer); + p += SecBuff[0].cbBuffer; + memcpy(p, SecBuff[1].pvBuffer, SecBuff[1].cbBuffer); + p += SecBuff[1].cbBuffer; + memcpy(p, SecBuff[2].pvBuffer, SecBuff[2].cbBuffer); +out_free: + free(SecBuff[0].pvBuffer); + free(SecBuff[2].pvBuffer); + + if (!maj_stat) + log_hexdump(0, "cipher:", bufout->value, bufout->length, 0); +out: + return maj_stat; +} + +uint32_t sspi_upwrap(PCtxtHandle ctx, sspi_buffer_desc *bufin, + sspi_buffer_desc *bufout, u_int *conf_state, + u_int *qop_state) +{ + uint32_t maj_stat; + SecBufferDesc BuffDesc; + SecBuffer SecBuff[2]; + ULONG ulQop = 0; + + BuffDesc.ulVersion = 0; + BuffDesc.cBuffers = 2; + BuffDesc.pBuffers = SecBuff; + + SecBuff[0].cbBuffer = bufin->length; + SecBuff[0].BufferType = SECBUFFER_STREAM; + SecBuff[0].pvBuffer = bufin->value; + + SecBuff[1].cbBuffer = 0; + SecBuff[1].BufferType = SECBUFFER_DATA; + SecBuff[1].pvBuffer = NULL; + + log_hexdump(0, "cipher:", bufin->value, bufin->length, 0); + + maj_stat = DecryptMessage(ctx, &BuffDesc, 0, &ulQop); + if (maj_stat != SEC_E_OK) return maj_stat; + + bufout->length = SecBuff[1].cbBuffer; + bufout->value = malloc(bufout->length); + memcpy(bufout->value, SecBuff[1].pvBuffer, bufout->length); + + log_hexdump(0, "data:", bufout->value, bufout->length, 0); + + *conf_state = 1; + *qop_state = 0; + + return SEC_E_OK; +} + /* useful as i add more mechanisms */ #define DEBUG #ifdef DEBUG diff --git a/libtirpc/src/auth_unix.c b/libtirpc/src/auth_unix.c index c3a69ad..84507b3 100644 --- a/libtirpc/src/auth_unix.c +++ b/libtirpc/src/auth_unix.c @@ -353,6 +353,12 @@ marshal_new_auth(auth) XDR_DESTROY(xdrs); } +static bool_t +authunix_wrap(AUTH *auth, XDR *xdrs, xdrproc_t func, caddr_t args, u_int seq) +{ + return ((*func)(xdrs, args)); +} + static struct auth_ops * authunix_ops() { @@ -368,6 +374,8 @@ authunix_ops() ops.ah_validate = authunix_validate; ops.ah_refresh = authunix_refresh; ops.ah_destroy = authunix_destroy; + ops.ah_wrap = authunix_wrap; + ops.ah_unwrap = authunix_wrap; } mutex_unlock(&ops_lock); return (&ops); diff --git a/libtirpc/src/authsspi_prot.c b/libtirpc/src/authsspi_prot.c index 09c0709..5539faa 100644 --- a/libtirpc/src/authsspi_prot.c +++ b/libtirpc/src/authsspi_prot.c @@ -108,7 +108,7 @@ xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, /* Skip databody length. */ start = XDR_GETPOS(xdrs); - //XDR_SETPOS(xdrs, start + 4); + XDR_SETPOS(xdrs, start + 4); /* Marshal rpc_gss_data_t (sequence number + arguments). */ if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr)) @@ -117,15 +117,14 @@ xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, /* Set databuf to marshalled rpc_gss_data_t. */ databuf.length = end - start - 4; - //XDR_SETPOS(xdrs, start + 4); - //databuf.value = XDR_INLINE(xdrs, databuf.length); - databuf.value = xdrrec_getoutbase(xdrs) + 1; + XDR_SETPOS(xdrs, start + 4); + databuf.value = XDR_INLINE(xdrs, databuf.length); xdr_stat = FALSE; if (svc == RPCSEC_SSPI_SVC_INTEGRITY) { /* Marshal databody_integ length. */ - //XDR_SETPOS(xdrs, start); + XDR_SETPOS(xdrs, start); if (!xdr_u_int(xdrs, (u_int *)&databuf.length)) return (FALSE); @@ -141,9 +140,9 @@ xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, return (FALSE); } /* Marshal checksum. */ - //XDR_SETPOS(xdrs, end); + XDR_SETPOS(xdrs, end); xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value, - (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ); + (u_int *)&wrapbuf.length, (u_int)-1); #if 0 gss_release_buffer(&min_stat, &wrapbuf); #else @@ -155,6 +154,8 @@ xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, #if 0 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf, &conf_state, &wrapbuf); +#else + maj_stat = sspi_wrap(ctx, 0, &databuf, &wrapbuf, &conf_state); #endif if (maj_stat != SEC_E_OK) { log_debug("xdr_rpc_sspi_wrap_data: sspi_wrap failed with %x", maj_stat); @@ -163,7 +164,7 @@ xdr_rpc_sspi_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, /* Marshal databody_priv. */ XDR_SETPOS(xdrs, start); xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value, - (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ); + (u_int *)&wrapbuf.length, (u_int)-1); #if 0 gss_release_buffer(&min_stat, &wrapbuf); #else @@ -196,7 +197,7 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, if (svc == RPCSEC_SSPI_SVC_INTEGRITY) { /* Decode databody_integ. */ if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length, - MAX_NETOBJ_SZ)) { + (u_int)-1)) { log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_integ failed"); return (FALSE); } @@ -224,7 +225,7 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, sspi_release_buffer(&wrapbuf); #endif - if (maj_stat != SEC_E_OK || qop_state != qop) { + if (maj_stat != SEC_E_OK) { #if 0 gss_release_buffer(&min_stat, &databuf); #else @@ -238,7 +239,7 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, else if (svc == RPCSEC_SSPI_SVC_PRIVACY) { /* Decode databody_priv. */ if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length, - MAX_NETOBJ_SZ)) { + (u_int)-1)) { log_debug("xdr_rpc_sspi_unwrap_data: xdr decode databody_priv failed"); return (FALSE); } @@ -246,6 +247,8 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, #if 0 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf, &conf_state, &qop_state); +#else + maj_stat = sspi_upwrap(ctx, &wrapbuf, &databuf, &conf_state, &qop_state); #endif #if 0 gss_release_buffer(&min_stat, &wrapbuf); @@ -253,8 +256,7 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, sspi_release_buffer(&wrapbuf); #endif /* Verify encryption and QOP. */ - if (maj_stat != SEC_E_OK || qop_state != qop || - conf_state != TRUE) { + if (maj_stat != SEC_E_OK) { #if 0 gss_release_buffer(&min_stat, &databuf); #else @@ -272,11 +274,12 @@ xdr_rpc_sspi_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, #if 0 gss_release_buffer(&min_stat, &databuf); #else - sspi_release_buffer(&databuf); + sspi_release_buffer(&databuf); #endif /* Verify sequence number. */ if (xdr_stat == TRUE && seq_num != seq) { - log_debug("wrong sequence number in databody"); + log_debug("wrong sequence number in databody received %d expected %d", + seq_num, seq); return (FALSE); } diff --git a/libtirpc/src/clnt_vc.c b/libtirpc/src/clnt_vc.c index 9ae30d6..5849a41 100644 --- a/libtirpc/src/clnt_vc.c +++ b/libtirpc/src/clnt_vc.c @@ -523,13 +523,14 @@ call_again: if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) || (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) || (! AUTH_MARSHALL(cl->cl_auth, xdrs, &seq)) || - (! (*xdr_args)(xdrs, args_ptr))) { + (! AUTH_WRAP(cl->cl_auth, xdrs, xdr_args, args_ptr))) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); release_fd_lock(ct->ct_fd, mask); return (ct->ct_error.re_status); } + if (! xdrrec_endofrecord(xdrs, shipnow)) { release_fd_lock(ct->ct_fd, mask); ct->ct_error.re_status = RPC_CANTSEND; @@ -552,7 +553,7 @@ call_again: /* * Keep receiving until we get a valid transaction id */ - + while (TRUE) { mutex_lock(&clnt_fd_lock); while ((vc_fd_locks[WINSOCK_HANDLE_HASH(ct->ct_fd)] && @@ -613,7 +614,8 @@ call_again: &ct->reply_msg.acpted_rply.ar_verf, seq)) { ct->ct_error.re_status = RPC_AUTHERROR; ct->ct_error.re_why = AUTH_INVALIDRESP; - } else if (! (*xdr_results)(xdrs, results_ptr)) { + } + else if (! AUTH_UNWRAP(cl->cl_auth, xdrs, xdr_results, results_ptr, seq)) { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTDECODERES; } diff --git a/libtirpc/tirpc/rpc/auth.h b/libtirpc/tirpc/rpc/auth.h index 82e0e33..d37c263 100644 --- a/libtirpc/tirpc/rpc/auth.h +++ b/libtirpc/tirpc/rpc/auth.h @@ -198,7 +198,7 @@ typedef struct __auth { /* encode data for wire */ int (*ah_wrap) (struct __auth *, XDR *, xdrproc_t, caddr_t); /* decode data for wire */ - int (*ah_unwrap) (struct __auth *, XDR *, xdrproc_t, caddr_t); + int (*ah_unwrap) (struct __auth *, XDR *, xdrproc_t, caddr_t, u_int); } *ah_ops; void *ah_private; @@ -245,12 +245,12 @@ typedef struct __auth { ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \ xfunc, xwhere)) -#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ +#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere, seq) \ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ - xfunc, xwhere)) -#define auth_unwrap(auth, xdrs, xfunc, xwhere) \ + xfunc, xwhere, seq)) +#define auth_unwrap(auth, xdrs, xfunc, xwhere, seq) \ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ - xfunc, xwhere)) + xfunc, xwhere, seq)) __BEGIN_DECLS diff --git a/libtirpc/tirpc/rpc/auth_sspi.h b/libtirpc/tirpc/rpc/auth_sspi.h index 5ebe4d8..53f06b6 100644 --- a/libtirpc/tirpc/rpc/auth_sspi.h +++ b/libtirpc/tirpc/rpc/auth_sspi.h @@ -105,6 +105,11 @@ uint32_t sspi_get_mic(void *ctx, u_int qop, u_int seq, sspi_buffer_desc *bufin, sspi_buffer_desc *bufout); uint32_t sspi_verify_mic(void *ctx, u_int seq, sspi_buffer_desc *bufin, sspi_buffer_desc *bufout, u_int *qop_state); +uint32_t sspi_wrap(void *ctx, u_int seq, sspi_buffer_desc *bufin, + sspi_buffer_desc *bufout, u_int *conf_state); +uint32_t sspi_unwrap(void *ctx, sspi_buffer_desc *bufin, + sspi_buffer_desc *bufout, u_int *conf_state, + u_int *qop_state); void sspi_release_buffer(sspi_buffer_desc *buf); uint32_t sspi_import_name(sspi_buffer_desc *name_in, sspi_name_t *name_out);