69 * unbind and teardown the connection. As each handle is initialized it
70 * will inherit a reference to the client context.
71 *
72 * Returns 0 or an NT_STATUS:
73 * NT_STATUS_BAD_NETWORK_PATH (get server addr)
74 * NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
75 * NT_STATUS_BAD_NETWORK_NAME (tcon, open)
76 * NT_STATUS_ACCESS_DENIED (open pipe)
77 * NT_STATUS_INVALID_PARAMETER (rpc bind)
78 *
79 * NT_STATUS_INTERNAL_ERROR (bad args etc)
80 * NT_STATUS_NO_MEMORY
81 */
82 DWORD
83 ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
84 char *username, const char *service)
85 {
86 struct smb_ctx *ctx = NULL;
87 ndr_client_t *clnt = NULL;
88 ndr_service_t *svc;
89 srvsvc_server_info_t svinfo;
90 DWORD status;
91 int fd = -1;
92 int rc;
93
94 if (handle == NULL || server == NULL || server[0] == '\0' ||
95 domain == NULL || username == NULL)
96 return (NT_STATUS_INTERNAL_ERROR);
97
98 /* In case the service was not registered... */
99 if ((svc = ndr_svc_lookup_name(service)) == NULL)
100 return (NT_STATUS_INTERNAL_ERROR);
101
102 /*
103 * Set the default based on the assumption that most
104 * servers will be Windows 2000 or later. This used to
105 * try to get the actual server version, but that RPC
106 * is not necessarily allowed anymore, so don't bother.
107 */
108 bzero(&svinfo, sizeof (srvsvc_server_info_t));
109 svinfo.sv_platform_id = SV_PLATFORM_ID_NT;
110 svinfo.sv_version_major = 5;
111 svinfo.sv_version_minor = 0;
112 svinfo.sv_type = SV_TYPE_DEFAULT;
113 svinfo.sv_os = NATIVE_OS_WIN2000;
114
115 /*
116 * Some callers pass this when they want a NULL session.
117 * Todo: have callers pass an empty string for that.
118 */
119 if (strcmp(username, MLSVC_ANON_USER) == 0)
120 username = "";
121
122 /*
123 * Setup smbfs library handle, authenticate, connect to
124 * the IPC$ share. This will reuse an existing connection
125 * if the driver already has one for this combination of
126 * server, user, domain. It may return any of:
127 * NT_STATUS_BAD_NETWORK_PATH (get server addr)
128 * NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
129 * NT_STATUS_BAD_NETWORK_NAME (tcon)
130 */
131 status = smbrdr_ctx_new(&ctx, server, domain, username);
132 if (status != NT_STATUS_SUCCESS) {
133 syslog(LOG_ERR, "ndr_rpc_bind: smbrdr_ctx_new"
134 "(Srv=%s Dom=%s User=%s), %s (0x%x)",
135 server, domain, username,
174 clnt->xa_read = ndr_xa_read;
175 clnt->xa_preserve = ndr_xa_preserve;
176 clnt->xa_destruct = ndr_xa_destruct;
177 clnt->xa_release = ndr_xa_release;
178 clnt->xa_private = ctx;
179 clnt->xa_fd = fd;
180
181 ndr_svc_binding_pool_init(&clnt->binding_list,
182 clnt->binding_pool, NDR_N_BINDING_POOL);
183
184 if ((clnt->heap = ndr_heap_create()) == NULL) {
185 status = NT_STATUS_NO_MEMORY;
186 goto errout;
187 }
188
189 /*
190 * Fill in the caller's handle.
191 */
192 bzero(&handle->handle, sizeof (ndr_hdid_t));
193 handle->clnt = clnt;
194 bcopy(&svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t));
195
196 /*
197 * Do the OtW RPC bind.
198 */
199 rc = ndr_clnt_bind(clnt, service, &clnt->binding);
200 switch (rc) {
201 case NDR_DRC_FAULT_OUT_OF_MEMORY:
202 status = NT_STATUS_NO_MEMORY;
203 break;
204 case NDR_DRC_FAULT_API_SERVICE_INVALID: /* not registered */
205 status = NT_STATUS_INTERNAL_ERROR;
206 break;
207 default:
208 if (NDR_DRC_IS_FAULT(rc)) {
209 status = NT_STATUS_INVALID_PARAMETER;
210 break;
211 }
212 /* FALLTHROUGH */
213 case NDR_DRC_OK:
214 return (NT_STATUS_SUCCESS);
286 clnt->nonull = B_FALSE;
287
288 if (NDR_DRC_IS_FAULT(rc)) {
289 ndr_rpc_release(handle);
290 return (-1);
291 }
292
293 return (0);
294 }
295
296 /*
297 * Outgoing strings should not be null terminated.
298 */
299 void
300 ndr_rpc_set_nonull(mlsvc_handle_t *handle)
301 {
302 handle->clnt->nonull = B_TRUE;
303 }
304
305 /*
306 * Return a reference to the server info.
307 */
308 const srvsvc_server_info_t *
309 ndr_rpc_server_info(mlsvc_handle_t *handle)
310 {
311 return (&handle->svinfo);
312 }
313
314 /*
315 * Return the RPC server OS level.
316 */
317 uint32_t
318 ndr_rpc_server_os(mlsvc_handle_t *handle)
319 {
320 return (handle->svinfo.sv_os);
321 }
322
323 /*
324 * Get the session key from a bound RPC client handle.
325 *
326 * The key returned is the 16-byte "user session key"
327 * established by the underlying authentication protocol
328 * (either Kerberos or NTLM). This key is needed for
329 * SAM RPC calls such as SamrSetInformationUser, etc.
330 * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25.
331 *
332 * Returns zero (success) or an errno.
333 */
334 int
335 ndr_rpc_get_ssnkey(mlsvc_handle_t *handle,
336 unsigned char *ssn_key, size_t len)
337 {
338 ndr_client_t *clnt = handle->clnt;
339 int rc;
340
341 if (clnt == NULL)
342 return (EINVAL);
343
404 return (B_FALSE);
405 }
406
407 /*
408 * Returns true if the handle is the top level bind handle.
409 * Otherwise returns false.
410 */
411 boolean_t
412 ndr_is_bind_handle(mlsvc_handle_t *handle)
413 {
414 return (handle->clnt->handle == &handle->handle);
415 }
416
417 /*
418 * Pass the client reference from parent to child.
419 */
420 void
421 ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent)
422 {
423 child->clnt = parent->clnt;
424 bcopy(&parent->svinfo, &child->svinfo, sizeof (srvsvc_server_info_t));
425 }
426
427 void
428 ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
429 {
430 ndr_service_t *svc;
431 char *name = "NDR RPC";
432 char *s = "unknown";
433
434 switch (NT_SC_SEVERITY(status)) {
435 case NT_STATUS_SEVERITY_SUCCESS:
436 s = "success";
437 break;
438 case NT_STATUS_SEVERITY_INFORMATIONAL:
439 s = "info";
440 break;
441 case NT_STATUS_SEVERITY_WARNING:
442 s = "warning";
443 break;
444 case NT_STATUS_SEVERITY_ERROR:
|
69 * unbind and teardown the connection. As each handle is initialized it
70 * will inherit a reference to the client context.
71 *
72 * Returns 0 or an NT_STATUS:
73 * NT_STATUS_BAD_NETWORK_PATH (get server addr)
74 * NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
75 * NT_STATUS_BAD_NETWORK_NAME (tcon, open)
76 * NT_STATUS_ACCESS_DENIED (open pipe)
77 * NT_STATUS_INVALID_PARAMETER (rpc bind)
78 *
79 * NT_STATUS_INTERNAL_ERROR (bad args etc)
80 * NT_STATUS_NO_MEMORY
81 */
82 DWORD
83 ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
84 char *username, const char *service)
85 {
86 struct smb_ctx *ctx = NULL;
87 ndr_client_t *clnt = NULL;
88 ndr_service_t *svc;
89 DWORD status;
90 int fd = -1;
91 int rc;
92
93 if (handle == NULL || server == NULL || server[0] == '\0' ||
94 domain == NULL || username == NULL)
95 return (NT_STATUS_INTERNAL_ERROR);
96
97 /* In case the service was not registered... */
98 if ((svc = ndr_svc_lookup_name(service)) == NULL)
99 return (NT_STATUS_INTERNAL_ERROR);
100
101 /*
102 * Some callers pass this when they want a NULL session.
103 * Todo: have callers pass an empty string for that.
104 */
105 if (strcmp(username, MLSVC_ANON_USER) == 0)
106 username = "";
107
108 /*
109 * Setup smbfs library handle, authenticate, connect to
110 * the IPC$ share. This will reuse an existing connection
111 * if the driver already has one for this combination of
112 * server, user, domain. It may return any of:
113 * NT_STATUS_BAD_NETWORK_PATH (get server addr)
114 * NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
115 * NT_STATUS_BAD_NETWORK_NAME (tcon)
116 */
117 status = smbrdr_ctx_new(&ctx, server, domain, username);
118 if (status != NT_STATUS_SUCCESS) {
119 syslog(LOG_ERR, "ndr_rpc_bind: smbrdr_ctx_new"
120 "(Srv=%s Dom=%s User=%s), %s (0x%x)",
121 server, domain, username,
160 clnt->xa_read = ndr_xa_read;
161 clnt->xa_preserve = ndr_xa_preserve;
162 clnt->xa_destruct = ndr_xa_destruct;
163 clnt->xa_release = ndr_xa_release;
164 clnt->xa_private = ctx;
165 clnt->xa_fd = fd;
166
167 ndr_svc_binding_pool_init(&clnt->binding_list,
168 clnt->binding_pool, NDR_N_BINDING_POOL);
169
170 if ((clnt->heap = ndr_heap_create()) == NULL) {
171 status = NT_STATUS_NO_MEMORY;
172 goto errout;
173 }
174
175 /*
176 * Fill in the caller's handle.
177 */
178 bzero(&handle->handle, sizeof (ndr_hdid_t));
179 handle->clnt = clnt;
180
181 /*
182 * Do the OtW RPC bind.
183 */
184 rc = ndr_clnt_bind(clnt, service, &clnt->binding);
185 switch (rc) {
186 case NDR_DRC_FAULT_OUT_OF_MEMORY:
187 status = NT_STATUS_NO_MEMORY;
188 break;
189 case NDR_DRC_FAULT_API_SERVICE_INVALID: /* not registered */
190 status = NT_STATUS_INTERNAL_ERROR;
191 break;
192 default:
193 if (NDR_DRC_IS_FAULT(rc)) {
194 status = NT_STATUS_INVALID_PARAMETER;
195 break;
196 }
197 /* FALLTHROUGH */
198 case NDR_DRC_OK:
199 return (NT_STATUS_SUCCESS);
271 clnt->nonull = B_FALSE;
272
273 if (NDR_DRC_IS_FAULT(rc)) {
274 ndr_rpc_release(handle);
275 return (-1);
276 }
277
278 return (0);
279 }
280
281 /*
282 * Outgoing strings should not be null terminated.
283 */
284 void
285 ndr_rpc_set_nonull(mlsvc_handle_t *handle)
286 {
287 handle->clnt->nonull = B_TRUE;
288 }
289
290 /*
291 * Get the session key from a bound RPC client handle.
292 *
293 * The key returned is the 16-byte "user session key"
294 * established by the underlying authentication protocol
295 * (either Kerberos or NTLM). This key is needed for
296 * SAM RPC calls such as SamrSetInformationUser, etc.
297 * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25.
298 *
299 * Returns zero (success) or an errno.
300 */
301 int
302 ndr_rpc_get_ssnkey(mlsvc_handle_t *handle,
303 unsigned char *ssn_key, size_t len)
304 {
305 ndr_client_t *clnt = handle->clnt;
306 int rc;
307
308 if (clnt == NULL)
309 return (EINVAL);
310
371 return (B_FALSE);
372 }
373
374 /*
375 * Returns true if the handle is the top level bind handle.
376 * Otherwise returns false.
377 */
378 boolean_t
379 ndr_is_bind_handle(mlsvc_handle_t *handle)
380 {
381 return (handle->clnt->handle == &handle->handle);
382 }
383
384 /*
385 * Pass the client reference from parent to child.
386 */
387 void
388 ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent)
389 {
390 child->clnt = parent->clnt;
391 }
392
393 void
394 ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
395 {
396 ndr_service_t *svc;
397 char *name = "NDR RPC";
398 char *s = "unknown";
399
400 switch (NT_SC_SEVERITY(status)) {
401 case NT_STATUS_SEVERITY_SUCCESS:
402 s = "success";
403 break;
404 case NT_STATUS_SEVERITY_INFORMATIONAL:
405 s = "info";
406 break;
407 case NT_STATUS_SEVERITY_WARNING:
408 s = "warning";
409 break;
410 case NT_STATUS_SEVERITY_ERROR:
|