example: Remove outdated config files from tridge
[Samba.git] / source3 / rpc_server / dfs / srv_dfs_nt.c
blob8eaa59a8b0e033f9947bb153c90e884c483c0c1d
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines for Dfs
4 * Copyright (C) Shirish Kalele 2000.
5 * Copyright (C) Jeremy Allison 2001-2007.
6 * Copyright (C) Jelmer Vernooij 2005-2006.
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.
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.
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/>.
22 /* This is the implementation of the dfs pipe. */
24 #include "includes.h"
25 #include "ntdomain.h"
26 #include "librpc/rpc/dcesrv_core.h"
27 #include "librpc/gen_ndr/ndr_dfs.h"
28 #include "librpc/gen_ndr/ndr_dfs_scompat.h"
29 #include "msdfs.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "auth.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_MSDFS
37 /* This function does not return a WERROR or NTSTATUS code but rather 1 if
38 dfs exists, or 0 otherwise. */
40 void _dfs_GetManagerVersion(struct pipes_struct *p, struct dfs_GetManagerVersion *r)
42 if (lp_host_msdfs()) {
43 *r->out.version = DFS_MANAGER_VERSION_NT4;
44 } else {
45 *r->out.version = (enum dfs_ManagerVersion)0;
49 WERROR _dfs_Add(struct pipes_struct *p, struct dfs_Add *r)
51 struct dcesrv_call_state *dce_call = p->dce_call;
52 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
53 const struct tsocket_address *local_address =
54 dcesrv_connection_get_local_address(dcesrv_conn);
55 const struct tsocket_address *remote_address =
56 dcesrv_connection_get_remote_address(dcesrv_conn);
57 struct auth_session_info *session_info =
58 dcesrv_call_session_info(dce_call);
59 struct junction_map *jn = NULL;
60 struct referral *old_referral_list = NULL;
61 bool self_ref = False;
62 size_t consumedcnt = 0;
63 char *altpath = NULL;
64 NTSTATUS status;
65 TALLOC_CTX *ctx = talloc_tos();
66 const char *pathnamep = r->in.path;
68 if (session_info->unix_token->uid != sec_initial_uid()) {
69 DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));
70 return WERR_ACCESS_DENIED;
73 jn = talloc_zero(ctx, struct junction_map);
74 if (!jn) {
75 return WERR_NOT_ENOUGH_MEMORY;
78 DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
79 r->in.path, r->in.server, r->in.share));
81 altpath = talloc_asprintf(ctx, "%s\\%s",
82 r->in.server,
83 r->in.share);
84 if (!altpath) {
85 return WERR_NOT_ENOUGH_MEMORY;
88 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
89 IS_DIRECTORY_SEP(pathnamep[1])) {
90 pathnamep++;
93 /* The following call can change the cwd. */
94 status = get_referred_path(ctx,
95 session_info,
96 pathnamep,
97 remote_address,
98 local_address,
99 jn, &consumedcnt, &self_ref);
100 if(!NT_STATUS_IS_OK(status)) {
101 return ntstatus_to_werror(status);
104 jn->referral_count += 1;
105 old_referral_list = jn->referral_list;
107 if (jn->referral_count < 1) {
108 return WERR_NOT_ENOUGH_MEMORY;
111 jn->referral_list = talloc_array(ctx, struct referral, jn->referral_count);
112 if(jn->referral_list == NULL) {
113 DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n"));
114 return WERR_NERR_DFSINTERNALERROR;
117 if(old_referral_list && jn->referral_list) {
118 memcpy(jn->referral_list, old_referral_list,
119 sizeof(struct referral)*jn->referral_count-1);
122 jn->referral_list[jn->referral_count-1].proximity = 0;
123 jn->referral_list[jn->referral_count-1].ttl = REFERRAL_TTL;
124 jn->referral_list[jn->referral_count-1].alternate_path = altpath;
126 if (!create_msdfs_link(jn, session_info)) {
127 return WERR_NERR_DFSCANTCREATEJUNCTIONPOINT;
130 return WERR_OK;
133 WERROR _dfs_Remove(struct pipes_struct *p, struct dfs_Remove *r)
135 struct dcesrv_call_state *dce_call = p->dce_call;
136 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
137 const struct tsocket_address *local_address =
138 dcesrv_connection_get_local_address(dcesrv_conn);
139 const struct tsocket_address *remote_address =
140 dcesrv_connection_get_remote_address(dcesrv_conn);
141 struct auth_session_info *session_info =
142 dcesrv_call_session_info(dce_call);
143 struct junction_map *jn = NULL;
144 bool self_ref = False;
145 size_t consumedcnt = 0;
146 bool found = False;
147 TALLOC_CTX *ctx = talloc_tos();
148 char *altpath = NULL;
149 NTSTATUS status;
150 const char *pathnamep = r->in.dfs_entry_path;
152 if (session_info->unix_token->uid != sec_initial_uid()) {
153 DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));
154 return WERR_ACCESS_DENIED;
157 jn = talloc_zero(ctx, struct junction_map);
158 if (!jn) {
159 return WERR_NOT_ENOUGH_MEMORY;
162 if (r->in.servername && r->in.sharename) {
163 altpath = talloc_asprintf(ctx, "%s\\%s",
164 r->in.servername,
165 r->in.sharename);
166 if (!altpath) {
167 return WERR_NOT_ENOUGH_MEMORY;
169 if (!strlower_m(altpath)) {
170 return WERR_INVALID_PARAMETER;
172 DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
173 r->in.dfs_entry_path, r->in.servername, r->in.sharename));
176 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
177 IS_DIRECTORY_SEP(pathnamep[1])) {
178 pathnamep++;
181 status = get_referred_path(ctx,
182 session_info,
183 pathnamep,
184 remote_address,
185 local_address,
186 jn, &consumedcnt, &self_ref);
187 if(!NT_STATUS_IS_OK(status)) {
188 return WERR_NERR_DFSNOSUCHVOLUME;
191 /* if no server-share pair given, remove the msdfs link completely */
192 if(!r->in.servername && !r->in.sharename) {
193 if(!remove_msdfs_link(jn, session_info)) {
194 return WERR_NERR_DFSNOSUCHVOLUME;
196 } else {
197 size_t i = 0;
198 /* compare each referral in the list with the one to remove */
199 DBG_DEBUG("altpath: .%s. refcnt: %zu\n",
200 altpath,
201 jn->referral_count);
202 for(i=0;i<jn->referral_count;i++) {
203 char *refpath = talloc_strdup(ctx,
204 jn->referral_list[i].alternate_path);
205 if (!refpath) {
206 return WERR_NOT_ENOUGH_MEMORY;
208 trim_char(refpath, '\\', '\\');
209 DEBUG(10,("_dfs_remove: refpath: .%s.\n", refpath));
210 if(strequal(refpath, altpath)) {
211 *(jn->referral_list[i].alternate_path)='\0';
212 DEBUG(10,("_dfs_remove: Removal request matches referral %s\n",
213 refpath));
214 found = True;
218 if(!found) {
219 return WERR_NERR_DFSNOSUCHSHARE;
222 /* Only one referral, remove it */
223 if(jn->referral_count == 1) {
224 if(!remove_msdfs_link(jn, session_info)) {
225 return WERR_NERR_DFSNOSUCHVOLUME;
227 } else {
228 if(!create_msdfs_link(jn, session_info)) {
229 return WERR_NERR_DFSCANTCREATEJUNCTIONPOINT;
234 return WERR_OK;
237 static bool init_reply_dfs_info_1(TALLOC_CTX *mem_ctx, struct junction_map* j,struct dfs_Info1* dfs1)
239 dfs1->path = talloc_asprintf(mem_ctx,
240 "\\\\%s\\%s\\%s", lp_netbios_name(),
241 j->service_name, j->volume_name);
242 if (dfs1->path == NULL)
243 return False;
245 DEBUG(5,("init_reply_dfs_info_1: initing entrypath: %s\n",dfs1->path));
246 return True;
249 static bool init_reply_dfs_info_2(TALLOC_CTX *mem_ctx, struct junction_map* j, struct dfs_Info2* dfs2)
251 dfs2->path = talloc_asprintf(mem_ctx,
252 "\\\\%s\\%s\\%s", lp_netbios_name(), j->service_name, j->volume_name);
253 if (dfs2->path == NULL)
254 return False;
255 dfs2->comment = talloc_strdup(mem_ctx, j->comment);
256 dfs2->state = 1; /* set up state of dfs junction as OK */
257 dfs2->num_stores = j->referral_count;
258 return True;
261 static bool init_reply_dfs_info_3(TALLOC_CTX *mem_ctx, struct junction_map* j, struct dfs_Info3* dfs3)
263 size_t ii;
264 if (j->volume_name[0] == '\0')
265 dfs3->path = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
266 lp_netbios_name(), j->service_name);
267 else
268 dfs3->path = talloc_asprintf(mem_ctx, "\\\\%s\\%s\\%s", lp_netbios_name(),
269 j->service_name, j->volume_name);
271 if (dfs3->path == NULL)
272 return False;
274 dfs3->comment = talloc_strdup(mem_ctx, j->comment);
275 dfs3->state = 1;
276 dfs3->num_stores = j->referral_count;
278 /* also enumerate the stores */
279 if (j->referral_count) {
280 dfs3->stores = talloc_array(mem_ctx, struct dfs_StorageInfo, j->referral_count);
281 if (!dfs3->stores)
282 return False;
283 memset(dfs3->stores, '\0', j->referral_count * sizeof(struct dfs_StorageInfo));
284 } else {
285 dfs3->stores = NULL;
288 for(ii=0;ii<j->referral_count;ii++) {
289 char* p;
290 char *path = NULL;
291 struct dfs_StorageInfo* stor = &(dfs3->stores[ii]);
292 struct referral* ref = &(j->referral_list[ii]);
294 path = talloc_strdup(mem_ctx, ref->alternate_path);
295 if (!path) {
296 return False;
298 trim_char(path,'\\','\0');
299 p = strrchr_m(path,'\\');
300 if(p==NULL) {
301 DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
302 continue;
304 *p = '\0';
305 DBG_INFO("storage %zu: %s.%s\n",ii,path,p+1);
306 stor->state = 2; /* set all stores as ONLINE */
307 stor->server = talloc_strdup(mem_ctx, path);
308 stor->share = talloc_strdup(mem_ctx, p+1);
310 return True;
313 static bool init_reply_dfs_info_100(TALLOC_CTX *mem_ctx, struct junction_map* j, struct dfs_Info100* dfs100)
315 dfs100->comment = talloc_strdup(mem_ctx, j->comment);
316 return True;
319 WERROR _dfs_Enum(struct pipes_struct *p, struct dfs_Enum *r)
321 struct dcesrv_call_state *dce_call = p->dce_call;
322 struct auth_session_info *session_info =
323 dcesrv_call_session_info(dce_call);
324 struct junction_map *jn = NULL;
325 size_t num_jn = 0;
326 size_t i;
327 TALLOC_CTX *ctx = talloc_tos();
329 jn = enum_msdfs_links(ctx, session_info, &num_jn);
330 if (!jn || num_jn == 0) {
331 num_jn = 0;
332 jn = NULL;
335 DEBUG(5,("_dfs_Enum: %u junctions found in Dfs, doing level %d\n",
336 (unsigned int)num_jn, r->in.level));
338 *r->out.total = num_jn;
340 /* Create the return array */
341 switch (r->in.level) {
342 case 1:
343 if (num_jn) {
344 if ((r->out.info->e.info1->s = talloc_array(ctx, struct dfs_Info1, num_jn)) == NULL) {
345 return WERR_NOT_ENOUGH_MEMORY;
347 } else {
348 r->out.info->e.info1->s = NULL;
350 r->out.info->e.info1->count = num_jn;
351 break;
352 case 2:
353 if (num_jn) {
354 if ((r->out.info->e.info2->s = talloc_array(ctx, struct dfs_Info2, num_jn)) == NULL) {
355 return WERR_NOT_ENOUGH_MEMORY;
357 } else {
358 r->out.info->e.info2->s = NULL;
360 r->out.info->e.info2->count = num_jn;
361 break;
362 case 3:
363 if (num_jn) {
364 if ((r->out.info->e.info3->s = talloc_array(ctx, struct dfs_Info3, num_jn)) == NULL) {
365 return WERR_NOT_ENOUGH_MEMORY;
367 } else {
368 r->out.info->e.info3->s = NULL;
370 r->out.info->e.info3->count = num_jn;
371 break;
372 default:
373 return WERR_INVALID_PARAMETER;
376 for (i = 0; i < num_jn; i++) {
377 switch (r->in.level) {
378 case 1:
379 init_reply_dfs_info_1(ctx, &jn[i], &r->out.info->e.info1->s[i]);
380 break;
381 case 2:
382 init_reply_dfs_info_2(ctx, &jn[i], &r->out.info->e.info2->s[i]);
383 break;
384 case 3:
385 init_reply_dfs_info_3(ctx, &jn[i], &r->out.info->e.info3->s[i]);
386 break;
387 default:
388 return WERR_INVALID_PARAMETER;
392 return WERR_OK;
395 WERROR _dfs_GetInfo(struct pipes_struct *p, struct dfs_GetInfo *r)
397 struct dcesrv_call_state *dce_call = p->dce_call;
398 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
399 const struct tsocket_address *local_address =
400 dcesrv_connection_get_local_address(dcesrv_conn);
401 const struct tsocket_address *remote_address =
402 dcesrv_connection_get_remote_address(dcesrv_conn);
403 struct auth_session_info *session_info =
404 dcesrv_call_session_info(dce_call);
405 size_t consumedcnt = 0;
406 struct junction_map *jn = NULL;
407 bool self_ref = False;
408 TALLOC_CTX *ctx = talloc_tos();
409 bool ret;
410 NTSTATUS status;
411 const char *pathnamep = r->in.dfs_entry_path;
413 jn = talloc_zero(ctx, struct junction_map);
414 if (!jn) {
415 return WERR_NOT_ENOUGH_MEMORY;
418 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
419 IS_DIRECTORY_SEP(pathnamep[1])) {
420 pathnamep++;
423 ret = create_junction(ctx, pathnamep, jn);
424 if (!ret) {
425 return WERR_NERR_DFSNOSUCHSERVER;
428 /* The following call can change the cwd. */
429 status = get_referred_path(ctx,
430 session_info,
431 pathnamep,
432 remote_address,
433 local_address,
434 jn, &consumedcnt, &self_ref);
435 if(!NT_STATUS_IS_OK(status) || consumedcnt < strlen(pathnamep)) {
436 return WERR_NERR_DFSNOSUCHVOLUME;
439 switch (r->in.level) {
440 case 1:
441 r->out.info->info1 = talloc_zero(ctx,struct dfs_Info1);
442 if (!r->out.info->info1) {
443 return WERR_NOT_ENOUGH_MEMORY;
445 ret = init_reply_dfs_info_1(ctx, jn, r->out.info->info1);
446 break;
447 case 2:
448 r->out.info->info2 = talloc_zero(ctx,struct dfs_Info2);
449 if (!r->out.info->info2) {
450 return WERR_NOT_ENOUGH_MEMORY;
452 ret = init_reply_dfs_info_2(ctx, jn, r->out.info->info2);
453 break;
454 case 3:
455 r->out.info->info3 = talloc_zero(ctx,struct dfs_Info3);
456 if (!r->out.info->info3) {
457 return WERR_NOT_ENOUGH_MEMORY;
459 ret = init_reply_dfs_info_3(ctx, jn, r->out.info->info3);
460 break;
461 case 100:
462 r->out.info->info100 = talloc_zero(ctx,struct dfs_Info100);
463 if (!r->out.info->info100) {
464 return WERR_NOT_ENOUGH_MEMORY;
466 ret = init_reply_dfs_info_100(ctx, jn, r->out.info->info100);
467 break;
468 default:
469 r->out.info->info1 = NULL;
470 return WERR_INVALID_PARAMETER;
473 if (!ret)
474 return WERR_INVALID_PARAMETER;
476 return WERR_OK;
479 WERROR _dfs_SetInfo(struct pipes_struct *p, struct dfs_SetInfo *r)
481 /* FIXME: Implement your code here */
482 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
483 return WERR_NOT_SUPPORTED;
486 WERROR _dfs_Rename(struct pipes_struct *p, struct dfs_Rename *r)
488 /* FIXME: Implement your code here */
489 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
490 return WERR_NOT_SUPPORTED;
493 WERROR _dfs_Move(struct pipes_struct *p, struct dfs_Move *r)
495 /* FIXME: Implement your code here */
496 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
497 return WERR_NOT_SUPPORTED;
500 WERROR _dfs_ManagerGetConfigInfo(struct pipes_struct *p, struct dfs_ManagerGetConfigInfo *r)
502 /* FIXME: Implement your code here */
503 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
504 return WERR_NOT_SUPPORTED;
507 WERROR _dfs_ManagerSendSiteInfo(struct pipes_struct *p, struct dfs_ManagerSendSiteInfo *r)
509 /* FIXME: Implement your code here */
510 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
511 return WERR_NOT_SUPPORTED;
514 WERROR _dfs_AddFtRoot(struct pipes_struct *p, struct dfs_AddFtRoot *r)
516 /* FIXME: Implement your code here */
517 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
518 return WERR_NOT_SUPPORTED;
521 WERROR _dfs_RemoveFtRoot(struct pipes_struct *p, struct dfs_RemoveFtRoot *r)
523 /* FIXME: Implement your code here */
524 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
525 return WERR_NOT_SUPPORTED;
528 WERROR _dfs_AddStdRoot(struct pipes_struct *p, struct dfs_AddStdRoot *r)
530 /* FIXME: Implement your code here */
531 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
532 return WERR_NOT_SUPPORTED;
535 WERROR _dfs_RemoveStdRoot(struct pipes_struct *p, struct dfs_RemoveStdRoot *r)
537 /* FIXME: Implement your code here */
538 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
539 return WERR_NOT_SUPPORTED;
542 WERROR _dfs_ManagerInitialize(struct pipes_struct *p, struct dfs_ManagerInitialize *r)
544 /* FIXME: Implement your code here */
545 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
546 return WERR_NOT_SUPPORTED;
549 WERROR _dfs_AddStdRootForced(struct pipes_struct *p, struct dfs_AddStdRootForced *r)
551 /* FIXME: Implement your code here */
552 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
553 return WERR_NOT_SUPPORTED;
556 WERROR _dfs_GetDcAddress(struct pipes_struct *p, struct dfs_GetDcAddress *r)
558 /* FIXME: Implement your code here */
559 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
560 return WERR_NOT_SUPPORTED;
563 WERROR _dfs_SetDcAddress(struct pipes_struct *p, struct dfs_SetDcAddress *r)
565 /* FIXME: Implement your code here */
566 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
567 return WERR_NOT_SUPPORTED;
570 WERROR _dfs_FlushFtTable(struct pipes_struct *p, struct dfs_FlushFtTable *r)
572 /* FIXME: Implement your code here */
573 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
574 return WERR_NOT_SUPPORTED;
577 WERROR _dfs_Add2(struct pipes_struct *p, struct dfs_Add2 *r)
579 /* FIXME: Implement your code here */
580 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
581 return WERR_NOT_SUPPORTED;
584 WERROR _dfs_Remove2(struct pipes_struct *p, struct dfs_Remove2 *r)
586 /* FIXME: Implement your code here */
587 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
588 return WERR_NOT_SUPPORTED;
591 WERROR _dfs_EnumEx(struct pipes_struct *p, struct dfs_EnumEx *r)
593 /* FIXME: Implement your code here */
594 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
595 return WERR_NOT_SUPPORTED;
598 WERROR _dfs_SetInfo2(struct pipes_struct *p, struct dfs_SetInfo2 *r)
600 /* FIXME: Implement your code here */
601 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
602 return WERR_NOT_SUPPORTED;
605 /* include the generated boilerplate */
606 #include "librpc/gen_ndr/ndr_dfs_scompat.c"