1/* 2 Unix SMB/CIFS implementation. 3 Main winbindd samba3 server routines 4 5 Copyright (C) Stefan Metzmacher 2005 6 Copyright (C) Volker Lendecke 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "winbind/wb_server.h" 24#include "smbd/service_stream.h" 25#include "lib/stream/packet.h" 26 27/* 28 work out if a packet is complete for protocols that use a 32 bit host byte 29 order length 30*/ 31NTSTATUS wbsrv_samba3_packet_full_request(void *private_data, DATA_BLOB blob, size_t *size) 32{ 33 uint32_t *len; 34 if (blob.length < 4) { 35 return STATUS_MORE_ENTRIES; 36 } 37 len = (uint32_t *)blob.data; 38 *size = (*len); 39 if (*size > blob.length) { 40 return STATUS_MORE_ENTRIES; 41 } 42 return NT_STATUS_OK; 43} 44 45 46NTSTATUS wbsrv_samba3_pull_request(DATA_BLOB blob, struct wbsrv_connection *wbconn, 47 struct wbsrv_samba3_call **_call) 48{ 49 struct wbsrv_samba3_call *call; 50 51 if (blob.length != sizeof(call->request)) { 52 DEBUG(0,("wbsrv_samba3_pull_request: invalid blob length %lu should be %lu\n" 53 " make sure you use the correct winbind client tools!\n", 54 (long)blob.length, (long)sizeof(call->request))); 55 return NT_STATUS_INVALID_PARAMETER; 56 } 57 58 call = talloc_zero(wbconn, struct wbsrv_samba3_call); 59 NT_STATUS_HAVE_NO_MEMORY(call); 60 61 /* the packet layout is the same as the in memory layout of the request, so just copy it */ 62 memcpy(&call->request, blob.data, sizeof(call->request)); 63 64 call->wbconn = wbconn; 65 call->event_ctx = call->wbconn->conn->event.ctx; 66 67 *_call = call; 68 return NT_STATUS_OK; 69} 70 71NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call) 72{ 73 DEBUG(10, ("Got winbind samba3 request %d\n", s3call->request.cmd)); 74 75 s3call->response.length = sizeof(s3call->response); 76 77 switch(s3call->request.cmd) { 78 case WINBINDD_INTERFACE_VERSION: 79 return wbsrv_samba3_interface_version(s3call); 80 81 case WINBINDD_CHECK_MACHACC: 82 return wbsrv_samba3_check_machacc(s3call); 83 84 case WINBINDD_PING: 85 return wbsrv_samba3_ping(s3call); 86 87 case WINBINDD_INFO: 88 return wbsrv_samba3_info(s3call); 89 90 case WINBINDD_DOMAIN_NAME: 91 return wbsrv_samba3_domain_name(s3call); 92 93 case WINBINDD_NETBIOS_NAME: 94 return wbsrv_samba3_netbios_name(s3call); 95 96 case WINBINDD_PRIV_PIPE_DIR: 97 return wbsrv_samba3_priv_pipe_dir(s3call); 98 99 case WINBINDD_LOOKUPNAME: 100 return wbsrv_samba3_lookupname(s3call); 101 102 case WINBINDD_LOOKUPSID: 103 return wbsrv_samba3_lookupsid(s3call); 104 105 case WINBINDD_PAM_AUTH: 106 return wbsrv_samba3_pam_auth(s3call); 107 108 case WINBINDD_PAM_AUTH_CRAP: 109 return wbsrv_samba3_pam_auth_crap(s3call); 110 111 case WINBINDD_GETDCNAME: 112 return wbsrv_samba3_getdcname(s3call); 113 114 case WINBINDD_GETUSERDOMGROUPS: 115 return wbsrv_samba3_userdomgroups(s3call); 116 117 case WINBINDD_GETUSERSIDS: 118 return wbsrv_samba3_usersids(s3call); 119 120 case WINBINDD_LIST_GROUPS: 121 return wbsrv_samba3_list_groups(s3call); 122 123 case WINBINDD_LIST_TRUSTDOM: 124 return wbsrv_samba3_list_trustdom(s3call); 125 126 case WINBINDD_LIST_USERS: 127 return wbsrv_samba3_list_users(s3call); 128 129 case WINBINDD_GETPWNAM: 130 return wbsrv_samba3_getpwnam(s3call); 131 132 case WINBINDD_GETPWUID: 133 return wbsrv_samba3_getpwuid(s3call); 134 135 case WINBINDD_SETPWENT: 136 return wbsrv_samba3_setpwent(s3call); 137 138 case WINBINDD_GETPWENT: 139 return wbsrv_samba3_getpwent(s3call); 140 141 case WINBINDD_ENDPWENT: 142 return wbsrv_samba3_endpwent(s3call); 143 144 case WINBINDD_GETGRNAM: 145 return wbsrv_samba3_getgrnam(s3call); 146 147 case WINBINDD_GETGRGID: 148 return wbsrv_samba3_getgrgid(s3call); 149 150 case WINBINDD_GETGROUPS: 151 return wbsrv_samba3_getgroups(s3call); 152 153 case WINBINDD_SETGRENT: 154 return wbsrv_samba3_setgrent(s3call); 155 156 case WINBINDD_GETGRENT: 157 return wbsrv_samba3_getgrent(s3call); 158 159 case WINBINDD_ENDGRENT: 160 return wbsrv_samba3_endgrent(s3call); 161 162 case WINBINDD_SID_TO_UID: 163 case WINBINDD_DUAL_SID2UID: 164 return wbsrv_samba3_sid2uid(s3call); 165 166 case WINBINDD_SID_TO_GID: 167 case WINBINDD_DUAL_SID2GID: 168 return wbsrv_samba3_sid2gid(s3call); 169 170 case WINBINDD_UID_TO_SID: 171 case WINBINDD_DUAL_UID2SID: 172 return wbsrv_samba3_uid2sid(s3call); 173 174 case WINBINDD_GID_TO_SID: 175 case WINBINDD_DUAL_GID2SID: 176 return wbsrv_samba3_gid2sid(s3call); 177 178 case WINBINDD_DOMAIN_INFO: 179 return wbsrv_samba3_domain_info(s3call); 180 181 /* Unimplemented commands */ 182 183 case WINBINDD_GETPWSID: 184 case WINBINDD_PAM_CHAUTHTOK: 185 case WINBINDD_PAM_LOGOFF: 186 case WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP: 187 case WINBINDD_LOOKUPRIDS: 188 case WINBINDD_SIDS_TO_XIDS: 189 case WINBINDD_ALLOCATE_UID: 190 case WINBINDD_ALLOCATE_GID: 191 case WINBINDD_SET_MAPPING: 192 case WINBINDD_REMOVE_MAPPING: 193 case WINBINDD_SET_HWM: 194 case WINBINDD_SHOW_SEQUENCE: 195 case WINBINDD_WINS_BYIP: 196 case WINBINDD_WINS_BYNAME: 197 case WINBINDD_GETGRLST: 198 case WINBINDD_GETSIDALIASES: 199 case WINBINDD_DSGETDCNAME: 200 case WINBINDD_INIT_CONNECTION: 201 case WINBINDD_DUAL_SIDS2XIDS: 202 case WINBINDD_DUAL_SET_MAPPING: 203 case WINBINDD_DUAL_REMOVE_MAPPING: 204 case WINBINDD_DUAL_SET_HWM: 205 case WINBINDD_DUAL_USERINFO: 206 case WINBINDD_DUAL_GETSIDALIASES: 207 case WINBINDD_DUAL_NDRCMD: 208 case WINBINDD_CCACHE_NTLMAUTH: 209 case WINBINDD_NUM_CMDS: 210 DEBUG(10, ("Unimplemented winbind samba3 request %d\n", 211 s3call->request.cmd)); 212 break; 213 } 214 215 s3call->response.result = WINBINDD_ERROR; 216 return NT_STATUS_OK; 217} 218 219static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_CTX *mem_ctx, DATA_BLOB *_blob) 220{ 221 DATA_BLOB blob; 222 uint8_t *extra_data; 223 size_t extra_data_len = 0; 224 225 extra_data = (uint8_t *)call->response.extra_data.data; 226 if (extra_data != NULL) { 227 extra_data_len = call->response.length - 228 sizeof(call->response); 229 } 230 231 blob = data_blob_talloc(mem_ctx, NULL, call->response.length); 232 NT_STATUS_HAVE_NO_MEMORY(blob.data); 233 234 /* don't push real pointer values into sockets */ 235 if (extra_data) { 236 call->response.extra_data.data = (void *)0xFFFFFFFF; 237 } 238 memcpy(blob.data, &call->response, sizeof(call->response)); 239 /* set back the pointer */ 240 call->response.extra_data.data = extra_data; 241 242 if (extra_data) { 243 memcpy(blob.data + sizeof(call->response), extra_data, extra_data_len); 244 } 245 246 *_blob = blob; 247 return NT_STATUS_OK; 248} 249 250/* 251 * queue a wbsrv_call reply on a wbsrv_connection 252 * NOTE: that this implies talloc_free(call), 253 * use talloc_reference(call) if you need it after 254 * calling wbsrv_queue_reply 255 */ 256NTSTATUS wbsrv_samba3_send_reply(struct wbsrv_samba3_call *call) 257{ 258 struct wbsrv_connection *wbconn = call->wbconn; 259 DATA_BLOB rep; 260 NTSTATUS status; 261 262 status = wbsrv_samba3_push_reply(call, call, &rep); 263 NT_STATUS_NOT_OK_RETURN(status); 264 265 status = packet_send(call->wbconn->packet, rep); 266 267 talloc_free(call); 268 269 if (!NT_STATUS_IS_OK(status)) { 270 wbsrv_terminate_connection(wbconn, 271 "failed to packet_send winbindd reply"); 272 return status; 273 } 274 /* the call isn't needed any more */ 275 return status; 276} 277 278NTSTATUS wbsrv_samba3_process(void *private_data, DATA_BLOB blob) 279{ 280 NTSTATUS status; 281 struct wbsrv_connection *wbconn = talloc_get_type(private_data, 282 struct wbsrv_connection); 283 struct wbsrv_samba3_call *call; 284 status = wbsrv_samba3_pull_request(blob, wbconn, &call); 285 286 if (!NT_STATUS_IS_OK(status)) { 287 return status; 288 } 289 290 status = wbsrv_samba3_handle_call(call); 291 292 if (!NT_STATUS_IS_OK(status)) { 293 talloc_free(call); 294 return status; 295 } 296 297 if (call->flags & WBSRV_CALL_FLAGS_REPLY_ASYNC) { 298 return NT_STATUS_OK; 299 } 300 301 status = wbsrv_samba3_send_reply(call); 302 return status; 303} 304 305