|
1 # |
|
2 # This patch allows for better interop with MS Windows clients accessing Solaris |
|
3 # SMB services. It fixes a few memory leaks and double frees found during SMB |
|
4 # stress testing. The CRs in order: |
|
5 # |
|
6 # 15580724 SUNBT6868908 Solaris acceptors should have returned KRB5KRB_AP_... |
|
7 # 15648322 SUNBT6959251 coredump in gss_release_name+0x36 |
|
8 # 20416772 spnego_gss_accept_sec_context issue with incorrect KRB OID |
|
9 # 16005842 Should retry SMB authentication upgrade to account for network... |
|
10 # 15579598 SUNBT6867208 Windows client cannot recover from KRB5KRB_AP_ERR_SKEW.. |
|
11 # |
|
12 # Note: MIT tickets will subsequently be filed, but the solution may differ from |
|
13 # what we currently offer in Solaris, because they may want the changes as the |
|
14 # default behavior therefore removing the dependency on the MS_INTEROP |
|
15 # environment variable. |
|
16 # Patch source: in-house |
|
17 # |
|
18 diff -pur old/src/lib/gssapi/krb5/accept_sec_context.c new/src/lib/gssapi/krb5/accept_sec_context.c |
|
19 --- old/src/lib/gssapi/krb5/accept_sec_context.c 2015-03-30 23:53:08.814324223 -0600 |
|
20 +++ new/src/lib/gssapi/krb5/accept_sec_context.c 2015-04-02 00:05:08.243563972 -0600 |
|
21 @@ -1226,6 +1226,35 @@ fail: |
|
22 */ |
|
23 memset(&krb_error_data, 0, sizeof(krb_error_data)); |
|
24 |
|
25 + /* |
|
26 + * We need to remap error conditions for buggy Windows clients if the |
|
27 + * MS_INTEROP env var has been set. |
|
28 + */ |
|
29 + if ((code == KRB5KRB_AP_ERR_BAD_INTEGRITY || |
|
30 + code == KRB5KRB_AP_ERR_NOKEY || code == KRB5KRB_AP_ERR_BADKEYVER) |
|
31 + && getenv("MS_INTEROP")) { |
|
32 + code = KRB5KRB_AP_ERR_MODIFIED; |
|
33 + major_status = GSS_S_CONTINUE_NEEDED; |
|
34 + } |
|
35 + |
|
36 + /* |
|
37 + * Set e-data to Windows constant (verified by MSFT). |
|
38 + * |
|
39 + * This facilitates the Windows CIFS client clock skew |
|
40 + * recovery feature. |
|
41 + */ |
|
42 + if (code == KRB5KRB_AP_ERR_SKEW && getenv("MS_INTEROP")) { |
|
43 + char *ms_e_data = "\x30\x05\xa1\x03\x02\x01\x02"; |
|
44 + int len = strlen(ms_e_data); |
|
45 + |
|
46 + krb_error_data.e_data.data = malloc(len); |
|
47 + if (krb_error_data.e_data.data) { |
|
48 + (void) memcpy(krb_error_data.e_data.data, ms_e_data, len); |
|
49 + krb_error_data.e_data.length = len; |
|
50 + } |
|
51 + major_status = GSS_S_CONTINUE_NEEDED; |
|
52 + } |
|
53 + |
|
54 code -= ERROR_TABLE_BASE_krb5; |
|
55 if (code < 0 || code > KRB_ERR_MAX) |
|
56 code = 60 /* KRB_ERR_GENERIC */; |
|
57 diff -pur old/src/lib/gssapi/spnego/spnego_mech.c new/src/lib/gssapi/spnego/spnego_mech.c |
|
58 --- old/src/lib/gssapi/spnego/spnego_mech.c 2015-03-30 23:53:08.816648991 -0600 |
|
59 +++ new/src/lib/gssapi/spnego/spnego_mech.c 2015-04-15 18:52:40.053965732 -0600 |
|
60 @@ -190,6 +190,13 @@ static const gss_OID_set_desc spnego_oid |
|
61 }; |
|
62 const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0; |
|
63 |
|
64 +/* encoded OID octet string for NTLMSSP security mechanism */ |
|
65 +#define GSS_MECH_NTLMSSP_OID_LENGTH 10 |
|
66 +#define GSS_MECH_NTLMSSP_OID "\053\006\001\004\001\202\067\002\002\012" |
|
67 +static gss_OID_desc ntlmssp_oid = { |
|
68 + GSS_MECH_NTLMSSP_OID_LENGTH, GSS_MECH_NTLMSSP_OID |
|
69 +}; |
|
70 + |
|
71 static int make_NegHints(OM_uint32 *, spnego_gss_cred_id_t, gss_buffer_t *); |
|
72 static int put_neg_hints(unsigned char **, gss_buffer_t, unsigned int); |
|
73 static OM_uint32 |
|
74 @@ -1243,7 +1250,7 @@ make_NegHints(OM_uint32 *minor_status, |
|
75 &hintNameBuf, |
|
76 &hintNameType); |
|
77 if (major_status != GSS_S_COMPLETE) { |
|
78 - gss_release_name(&minor, &hintName); |
|
79 + gss_release_name(&minor, &hintKerberosName); |
|
80 return (major_status); |
|
81 } |
|
82 gss_release_name(&minor, &hintKerberosName); |
|
83 @@ -1386,6 +1393,7 @@ acc_ctx_new(OM_uint32 *minor_status, |
|
84 gss_buffer_desc der_mechTypes; |
|
85 gss_OID mech_wanted; |
|
86 spnego_gss_ctx_id_t sc = NULL; |
|
87 + unsigned int i; |
|
88 |
|
89 ret = GSS_S_DEFECTIVE_TOKEN; |
|
90 der_mechTypes.length = 0; |
|
91 @@ -1409,6 +1417,24 @@ acc_ctx_new(OM_uint32 *minor_status, |
|
92 goto cleanup; |
|
93 } |
|
94 /* |
|
95 + * We add KRB5_WRONG here so that old MS clients can negotiate this |
|
96 + * mechanism, which allows extensions in Kerberos (clock skew |
|
97 + * adjustment, refresh ccache). |
|
98 + */ |
|
99 + for (i = 0; i < supported_mechSet->count; i++) { |
|
100 + if (is_kerb_mech(&supported_mechSet->elements[i])) { |
|
101 + extern gss_OID_desc * const gss_mech_krb5_wrong; |
|
102 + ret = gss_add_oid_set_member(minor_status, |
|
103 + gss_mech_krb5_wrong, |
|
104 + &supported_mechSet); |
|
105 + if (ret != GSS_S_COMPLETE) { |
|
106 + *return_token = NO_TOKEN_SEND; |
|
107 + goto cleanup; |
|
108 + } |
|
109 + break; |
|
110 + } |
|
111 + } |
|
112 + /* |
|
113 * Select the best match between the list of mechs |
|
114 * that the initiator requested and the list that |
|
115 * the acceptor will support. |
|
116 @@ -2989,6 +3015,7 @@ get_available_mechs(OM_uint32 *minor_sta |
|
117 int found = 0; |
|
118 OM_uint32 major_status = GSS_S_COMPLETE, tmpmin; |
|
119 gss_OID_set mechs, goodmechs; |
|
120 + char *msinterop = getenv("MS_INTEROP"); |
|
121 |
|
122 major_status = gss_indicate_mechs(minor_status, &mechs); |
|
123 |
|
124 @@ -3003,6 +3030,15 @@ get_available_mechs(OM_uint32 *minor_sta |
|
125 return (major_status); |
|
126 } |
|
127 |
|
128 + /* |
|
129 + * If the required keytab entries for Kerberized SMB service are |
|
130 + * missing due to an SMB authentication upgrade failure, SMB daemon |
|
131 + * will set MS_INTEROP environmment variable to 1 to ensure only |
|
132 + * NTLMSSP security mech is used for negotiation. |
|
133 + */ |
|
134 + if ((msinterop != NULL) && (!strcmp(msinterop, "1"))) |
|
135 + goto ntlmssp; |
|
136 + |
|
137 for (i = 0; i < mechs->count && major_status == GSS_S_COMPLETE; i++) { |
|
138 if ((mechs->elements[i].length |
|
139 != spnego_mechanism.mech_type.length) || |
|
140 @@ -3018,6 +3054,25 @@ get_available_mechs(OM_uint32 *minor_sta |
|
141 } |
|
142 } |
|
143 |
|
144 +ntlmssp: |
|
145 + /* |
|
146 + * Add NTLMSSP OID to the mech OID set only if MS_INTEROP env var has |
|
147 + * been set to: |
|
148 + * - "1" (NTLMSSP only) or |
|
149 + * - "2" (both Krb5 and NTLMSSP) |
|
150 + * |
|
151 + * This is a requirement until NTLMSSP is implemented as a GSS-API |
|
152 + * plugin. |
|
153 + */ |
|
154 + if ((msinterop != NULL) && |
|
155 + (!strcmp(msinterop, "1") || !strcmp(msinterop, "2"))) { |
|
156 + major_status = gss_add_oid_set_member(minor_status, |
|
157 + &ntlmssp_oid, rmechs); |
|
158 + |
|
159 + if (major_status == GSS_S_COMPLETE) |
|
160 + found++; |
|
161 + } |
|
162 + |
|
163 /* |
|
164 * If the caller wanted a list of creds returned, |
|
165 * trim the list of mechanisms down to only those |
|
166 @@ -3593,9 +3648,17 @@ negotiate_mech(gss_OID_set supported, gs |
|
167 for (i = 0; i < received->count; i++) { |
|
168 gss_OID mech_oid = &received->elements[i]; |
|
169 |
|
170 + /* |
|
171 + * MIT compares against MS' wrong OID, but we actually want to |
|
172 + * select it if the client supports, as this will enable |
|
173 + * features on MS clients that allow credential refresh on |
|
174 + * rekeying and caching system times from servers. |
|
175 + */ |
|
176 +#if 0 |
|
177 /* Accept wrong mechanism OID from MS clients */ |
|
178 if (g_OID_equal(mech_oid, &gss_mech_krb5_wrong_oid)) |
|
179 mech_oid = (gss_OID)&gss_mech_krb5_oid; |
|
180 +#endif |
|
181 |
|
182 for (j = 0; j < supported->count; j++) { |
|
183 if (g_OID_equal(mech_oid, &supported->elements[j])) { |