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. */
27 #define DBGC_CLASS DBGC_MSDFS
29 /* This function does not return a WERROR or NTSTATUS code but rather 1 if
30 dfs exists, or 0 otherwise. */
32 void _dfs_GetManagerVersion(pipes_struct
*p
, struct dfs_GetManagerVersion
*r
)
34 if (lp_host_msdfs()) {
35 *r
->out
.version
= DFS_MANAGER_VERSION_NT4
;
37 *r
->out
.version
= (enum dfs_ManagerVersion
)0;
41 WERROR
_dfs_Add(pipes_struct
*p
, struct dfs_Add
*r
)
43 struct junction_map
*jn
= NULL
;
44 struct referral
*old_referral_list
= NULL
;
45 bool self_ref
= False
;
49 TALLOC_CTX
*ctx
= talloc_tos();
51 if (p
->pipe_user
.ut
.uid
!= sec_initial_uid()) {
52 DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));
53 return WERR_ACCESS_DENIED
;
56 jn
= TALLOC_ZERO_P(ctx
, struct junction_map
);
61 DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
62 r
->in
.path
, r
->in
.server
, r
->in
.share
));
64 altpath
= talloc_asprintf(ctx
, "%s\\%s",
71 /* The following call can change the cwd. */
72 status
= get_referred_path(ctx
, r
->in
.path
, jn
,
73 &consumedcnt
, &self_ref
);
74 if(!NT_STATUS_IS_OK(status
)) {
75 return ntstatus_to_werror(status
);
78 jn
->referral_count
+= 1;
79 old_referral_list
= jn
->referral_list
;
81 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
83 if (jn
->referral_count
< 1) {
87 jn
->referral_list
= TALLOC_ARRAY(ctx
, struct referral
, jn
->referral_count
);
88 if(jn
->referral_list
== NULL
) {
89 DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n"));
90 return WERR_DFS_INTERNAL_ERROR
;
93 if(old_referral_list
&& jn
->referral_list
) {
94 memcpy(jn
->referral_list
, old_referral_list
,
95 sizeof(struct referral
)*jn
->referral_count
-1);
98 jn
->referral_list
[jn
->referral_count
-1].proximity
= 0;
99 jn
->referral_list
[jn
->referral_count
-1].ttl
= REFERRAL_TTL
;
100 jn
->referral_list
[jn
->referral_count
-1].alternate_path
= altpath
;
102 if(!create_msdfs_link(jn
)) {
103 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
104 return WERR_DFS_CANT_CREATE_JUNCT
;
106 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
111 WERROR
_dfs_Remove(pipes_struct
*p
, struct dfs_Remove
*r
)
113 struct junction_map
*jn
= NULL
;
114 bool self_ref
= False
;
117 TALLOC_CTX
*ctx
= talloc_tos();
118 char *altpath
= NULL
;
120 if (p
->pipe_user
.ut
.uid
!= sec_initial_uid()) {
121 DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));
122 return WERR_ACCESS_DENIED
;
125 jn
= TALLOC_ZERO_P(ctx
, struct junction_map
);
130 if (r
->in
.servername
&& r
->in
.sharename
) {
131 altpath
= talloc_asprintf(ctx
, "%s\\%s",
138 DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
139 r
->in
.dfs_entry_path
, r
->in
.servername
, r
->in
.sharename
));
142 if(!NT_STATUS_IS_OK(get_referred_path(ctx
, r
->in
.dfs_entry_path
, jn
,
143 &consumedcnt
, &self_ref
))) {
144 return WERR_DFS_NO_SUCH_VOL
;
147 /* if no server-share pair given, remove the msdfs link completely */
148 if(!r
->in
.servername
&& !r
->in
.sharename
) {
149 if(!remove_msdfs_link(jn
)) {
150 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
151 return WERR_DFS_NO_SUCH_VOL
;
153 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
156 /* compare each referral in the list with the one to remove */
157 DEBUG(10,("altpath: .%s. refcnt: %d\n", altpath
, jn
->referral_count
));
158 for(i
=0;i
<jn
->referral_count
;i
++) {
159 char *refpath
= talloc_strdup(ctx
,
160 jn
->referral_list
[i
].alternate_path
);
164 trim_char(refpath
, '\\', '\\');
165 DEBUG(10,("_dfs_remove: refpath: .%s.\n", refpath
));
166 if(strequal(refpath
, altpath
)) {
167 *(jn
->referral_list
[i
].alternate_path
)='\0';
168 DEBUG(10,("_dfs_remove: Removal request matches referral %s\n",
175 return WERR_DFS_NO_SUCH_SHARE
;
178 /* Only one referral, remove it */
179 if(jn
->referral_count
== 1) {
180 if(!remove_msdfs_link(jn
)) {
181 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
182 return WERR_DFS_NO_SUCH_VOL
;
185 if(!create_msdfs_link(jn
)) {
186 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
187 return WERR_DFS_CANT_CREATE_JUNCT
;
190 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
196 static bool init_reply_dfs_info_1(TALLOC_CTX
*mem_ctx
, struct junction_map
* j
,struct dfs_Info1
* dfs1
)
198 dfs1
->path
= talloc_asprintf(mem_ctx
,
199 "\\\\%s\\%s\\%s", global_myname(),
200 j
->service_name
, j
->volume_name
);
201 if (dfs1
->path
== NULL
)
204 DEBUG(5,("init_reply_dfs_info_1: initing entrypath: %s\n",dfs1
->path
));
208 static bool init_reply_dfs_info_2(TALLOC_CTX
*mem_ctx
, struct junction_map
* j
, struct dfs_Info2
* dfs2
)
210 dfs2
->path
= talloc_asprintf(mem_ctx
,
211 "\\\\%s\\%s\\%s", global_myname(), j
->service_name
, j
->volume_name
);
212 if (dfs2
->path
== NULL
)
214 dfs2
->comment
= talloc_strdup(mem_ctx
, j
->comment
);
215 dfs2
->state
= 1; /* set up state of dfs junction as OK */
216 dfs2
->num_stores
= j
->referral_count
;
220 static bool init_reply_dfs_info_3(TALLOC_CTX
*mem_ctx
, struct junction_map
* j
, struct dfs_Info3
* dfs3
)
223 if (j
->volume_name
[0] == '\0')
224 dfs3
->path
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
225 global_myname(), j
->service_name
);
227 dfs3
->path
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s\\%s", global_myname(),
228 j
->service_name
, j
->volume_name
);
230 if (dfs3
->path
== NULL
)
233 dfs3
->comment
= talloc_strdup(mem_ctx
, j
->comment
);
235 dfs3
->num_stores
= j
->referral_count
;
237 /* also enumerate the stores */
238 if (j
->referral_count
) {
239 dfs3
->stores
= TALLOC_ARRAY(mem_ctx
, struct dfs_StorageInfo
, j
->referral_count
);
242 memset(dfs3
->stores
, '\0', j
->referral_count
* sizeof(struct dfs_StorageInfo
));
247 for(ii
=0;ii
<j
->referral_count
;ii
++) {
250 struct dfs_StorageInfo
* stor
= &(dfs3
->stores
[ii
]);
251 struct referral
* ref
= &(j
->referral_list
[ii
]);
253 path
= talloc_strdup(mem_ctx
, ref
->alternate_path
);
257 trim_char(path
,'\\','\0');
258 p
= strrchr_m(path
,'\\');
260 DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path
));
264 DEBUG(5,("storage %d: %s.%s\n",ii
,path
,p
+1));
265 stor
->state
= 2; /* set all stores as ONLINE */
266 stor
->server
= talloc_strdup(mem_ctx
, path
);
267 stor
->share
= talloc_strdup(mem_ctx
, p
+1);
272 static bool init_reply_dfs_info_100(TALLOC_CTX
*mem_ctx
, struct junction_map
* j
, struct dfs_Info100
* dfs100
)
274 dfs100
->comment
= talloc_strdup(mem_ctx
, j
->comment
);
278 WERROR
_dfs_Enum(pipes_struct
*p
, struct dfs_Enum
*r
)
280 struct junction_map
*jn
= NULL
;
283 TALLOC_CTX
*ctx
= talloc_tos();
285 jn
= enum_msdfs_links(ctx
, &num_jn
);
286 if (!jn
|| num_jn
== 0) {
290 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
292 DEBUG(5,("_dfs_Enum: %u junctions found in Dfs, doing level %d\n",
293 (unsigned int)num_jn
, r
->in
.level
));
295 *r
->out
.total
= num_jn
;
297 /* Create the return array */
298 switch (r
->in
.level
) {
301 if ((r
->out
.info
->e
.info1
->s
= TALLOC_ARRAY(ctx
, struct dfs_Info1
, num_jn
)) == NULL
) {
305 r
->out
.info
->e
.info1
->s
= NULL
;
307 r
->out
.info
->e
.info1
->count
= num_jn
;
311 if ((r
->out
.info
->e
.info2
->s
= TALLOC_ARRAY(ctx
, struct dfs_Info2
, num_jn
)) == NULL
) {
315 r
->out
.info
->e
.info2
->s
= NULL
;
317 r
->out
.info
->e
.info2
->count
= num_jn
;
321 if ((r
->out
.info
->e
.info3
->s
= TALLOC_ARRAY(ctx
, struct dfs_Info3
, num_jn
)) == NULL
) {
325 r
->out
.info
->e
.info3
->s
= NULL
;
327 r
->out
.info
->e
.info3
->count
= num_jn
;
330 return WERR_INVALID_PARAM
;
333 for (i
= 0; i
< num_jn
; i
++) {
334 switch (r
->in
.level
) {
336 init_reply_dfs_info_1(ctx
, &jn
[i
], &r
->out
.info
->e
.info1
->s
[i
]);
339 init_reply_dfs_info_2(ctx
, &jn
[i
], &r
->out
.info
->e
.info2
->s
[i
]);
342 init_reply_dfs_info_3(ctx
, &jn
[i
], &r
->out
.info
->e
.info3
->s
[i
]);
345 return WERR_INVALID_PARAM
;
352 WERROR
_dfs_GetInfo(pipes_struct
*p
, struct dfs_GetInfo
*r
)
354 int consumedcnt
= strlen(r
->in
.dfs_entry_path
);
355 struct junction_map
*jn
= NULL
;
356 bool self_ref
= False
;
357 TALLOC_CTX
*ctx
= talloc_tos();
360 jn
= TALLOC_ZERO_P(ctx
, struct junction_map
);
365 if(!create_junction(ctx
, r
->in
.dfs_entry_path
, jn
)) {
366 return WERR_DFS_NO_SUCH_SERVER
;
369 /* The following call can change the cwd. */
370 if(!NT_STATUS_IS_OK(get_referred_path(ctx
, r
->in
.dfs_entry_path
,
371 jn
, &consumedcnt
, &self_ref
)) ||
372 consumedcnt
< strlen(r
->in
.dfs_entry_path
)) {
373 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
374 return WERR_DFS_NO_SUCH_VOL
;
377 vfs_ChDir(p
->conn
,p
->conn
->connectpath
);
379 switch (r
->in
.level
) {
381 r
->out
.info
->info1
= TALLOC_ZERO_P(ctx
,struct dfs_Info1
);
382 if (!r
->out
.info
->info1
) {
385 ret
= init_reply_dfs_info_1(ctx
, jn
, r
->out
.info
->info1
);
388 r
->out
.info
->info2
= TALLOC_ZERO_P(ctx
,struct dfs_Info2
);
389 if (!r
->out
.info
->info2
) {
392 ret
= init_reply_dfs_info_2(ctx
, jn
, r
->out
.info
->info2
);
395 r
->out
.info
->info3
= TALLOC_ZERO_P(ctx
,struct dfs_Info3
);
396 if (!r
->out
.info
->info3
) {
399 ret
= init_reply_dfs_info_3(ctx
, jn
, r
->out
.info
->info3
);
402 r
->out
.info
->info100
= TALLOC_ZERO_P(ctx
,struct dfs_Info100
);
403 if (!r
->out
.info
->info100
) {
406 ret
= init_reply_dfs_info_100(ctx
, jn
, r
->out
.info
->info100
);
409 r
->out
.info
->info1
= NULL
;
410 return WERR_INVALID_PARAM
;
414 return WERR_INVALID_PARAM
;
419 WERROR
_dfs_SetInfo(pipes_struct
*p
, struct dfs_SetInfo
*r
)
421 /* FIXME: Implement your code here */
422 p
->rng_fault_state
= True
;
423 return WERR_NOT_SUPPORTED
;
426 WERROR
_dfs_Rename(pipes_struct
*p
, struct dfs_Rename
*r
)
428 /* FIXME: Implement your code here */
429 p
->rng_fault_state
= True
;
430 return WERR_NOT_SUPPORTED
;
433 WERROR
_dfs_Move(pipes_struct
*p
, struct dfs_Move
*r
)
435 /* FIXME: Implement your code here */
436 p
->rng_fault_state
= True
;
437 return WERR_NOT_SUPPORTED
;
440 WERROR
_dfs_ManagerGetConfigInfo(pipes_struct
*p
, struct dfs_ManagerGetConfigInfo
*r
)
442 /* FIXME: Implement your code here */
443 p
->rng_fault_state
= True
;
444 return WERR_NOT_SUPPORTED
;
447 WERROR
_dfs_ManagerSendSiteInfo(pipes_struct
*p
, struct dfs_ManagerSendSiteInfo
*r
)
449 /* FIXME: Implement your code here */
450 p
->rng_fault_state
= True
;
451 return WERR_NOT_SUPPORTED
;
454 WERROR
_dfs_AddFtRoot(pipes_struct
*p
, struct dfs_AddFtRoot
*r
)
456 /* FIXME: Implement your code here */
457 p
->rng_fault_state
= True
;
458 return WERR_NOT_SUPPORTED
;
461 WERROR
_dfs_RemoveFtRoot(pipes_struct
*p
, struct dfs_RemoveFtRoot
*r
)
463 /* FIXME: Implement your code here */
464 p
->rng_fault_state
= True
;
465 return WERR_NOT_SUPPORTED
;
468 WERROR
_dfs_AddStdRoot(pipes_struct
*p
, struct dfs_AddStdRoot
*r
)
470 /* FIXME: Implement your code here */
471 p
->rng_fault_state
= True
;
472 return WERR_NOT_SUPPORTED
;
475 WERROR
_dfs_RemoveStdRoot(pipes_struct
*p
, struct dfs_RemoveStdRoot
*r
)
477 /* FIXME: Implement your code here */
478 p
->rng_fault_state
= True
;
479 return WERR_NOT_SUPPORTED
;
482 WERROR
_dfs_ManagerInitialize(pipes_struct
*p
, struct dfs_ManagerInitialize
*r
)
484 /* FIXME: Implement your code here */
485 p
->rng_fault_state
= True
;
486 return WERR_NOT_SUPPORTED
;
489 WERROR
_dfs_AddStdRootForced(pipes_struct
*p
, struct dfs_AddStdRootForced
*r
)
491 /* FIXME: Implement your code here */
492 p
->rng_fault_state
= True
;
493 return WERR_NOT_SUPPORTED
;
496 WERROR
_dfs_GetDcAddress(pipes_struct
*p
, struct dfs_GetDcAddress
*r
)
498 /* FIXME: Implement your code here */
499 p
->rng_fault_state
= True
;
500 return WERR_NOT_SUPPORTED
;
503 WERROR
_dfs_SetDcAddress(pipes_struct
*p
, struct dfs_SetDcAddress
*r
)
505 /* FIXME: Implement your code here */
506 p
->rng_fault_state
= True
;
507 return WERR_NOT_SUPPORTED
;
510 WERROR
_dfs_FlushFtTable(pipes_struct
*p
, struct dfs_FlushFtTable
*r
)
512 /* FIXME: Implement your code here */
513 p
->rng_fault_state
= True
;
514 return WERR_NOT_SUPPORTED
;
517 WERROR
_dfs_Add2(pipes_struct
*p
, struct dfs_Add2
*r
)
519 /* FIXME: Implement your code here */
520 p
->rng_fault_state
= True
;
521 return WERR_NOT_SUPPORTED
;
524 WERROR
_dfs_Remove2(pipes_struct
*p
, struct dfs_Remove2
*r
)
526 /* FIXME: Implement your code here */
527 p
->rng_fault_state
= True
;
528 return WERR_NOT_SUPPORTED
;
531 WERROR
_dfs_EnumEx(pipes_struct
*p
, struct dfs_EnumEx
*r
)
533 /* FIXME: Implement your code here */
534 p
->rng_fault_state
= True
;
535 return WERR_NOT_SUPPORTED
;
538 WERROR
_dfs_SetInfo2(pipes_struct
*p
, struct dfs_SetInfo2
*r
)
540 /* FIXME: Implement your code here */
541 p
->rng_fault_state
= True
;
542 return WERR_NOT_SUPPORTED
;