source: branches/client-3.0/src/smbwrp.c@ 930

Last change on this file since 930 was 930, checked in by Paul Smedley, 9 years ago

Add support to enable Kerberos support, and make the plugin connect using kerberos when it's enabled

  • Property svn:eol-style set to native
File size: 30.6 KB
Line 
1/*
2 Netdrive Samba client plugin
3 samba library wrappers
4 Copyright (C) netlabs.org 2003-2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22#include "rpc_client/cli_pipe.h"
23#include "librpc/gen_ndr/ndr_srvsvc_c.h"
24#include "libsmb/libsmb.h"
25#include "libsmb/clirap.h"
26#include "param.h"
27#include "smb/smbXcli_base.h"
28#include "trans2.h"
29#include "smbwrp.h"
30#include "util.h"
31
32/*
33 * Wrapper for cli_errno to return not connected error on negative fd
34 * Now returns an OS/2 return code instead of lerrno.
35 */
36int os2cli_errno(cli_state * cli)
37{
38#if 0 // cli->fd not available in Samba 4.x
39 if (cli->fd == -1)
40 {
41 return maperror( ENOTCONN);
42 }
43#endif
44 return maperror(cli_errno(cli));
45}
46
47void smbwrp_Logging()
48{
49 char slogfile[_MAX_PATH +1] = {0};
50 char slogfilename[] = "log.smbc";
51 char *env = getenv("LOGFILES");
52 if (env != NULL)
53 {
54 strncpy(slogfile, env, sizeof(slogfile) -1);
55 strncat(slogfile, "\\", sizeof(slogfile) - strlen(slogfile) -1);
56 strncat(slogfile, slogfilename, sizeof(slogfile) - strlen(slogfile) -1);
57 }
58 else
59 {
60 strncpy(slogfile, slogfilename, sizeof(slogfile) -1);
61 }
62
63 // init samba for debug messages
64 setup_logging(slogfile, DEBUG_FILE);
65 lp_set_logfile(slogfile);
66 reopen_logs();
67}
68
69const char * smbwrp_getVersion()
70{
71 return samba_version_string();
72}
73
74int _System smbwrp_getclisize(void)
75{
76 return sizeof(struct cli_state);
77}
78
79/*****************************************************
80initialise structures
81*******************************************************/
82int _System smbwrp_init(void)
83{
84 static int initialised = 0;
85 char *p;
86
87 struct loadparm_context *lp_ctx;
88 TALLOC_CTX *frame = talloc_stackframe();
89
90 if (initialised)
91 {
92 return 0;
93 }
94 initialised = 1;
95
96 smb_init_locale();
97
98 if (!lp_load_client(get_dyn_CONFIGFILE())) {
99 debuglocal(0,("Can't load %s, defaults are used!\n",get_dyn_CONFIGFILE()));
100 }
101 load_interfaces();
102
103 if (!init_names())
104 {
105 return 1;
106 }
107
108 if (writeLog())
109 {
110 smbwrp_Logging();
111 }
112
113/*
114 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
115 lp_set_name_resolve_order(p);
116 }
117*/
118 return 0;
119
120}
121
122void smbwrp_initthread(void)
123{
124 /*
125 Block SIGPIPE (from lib/util_sock.c: write())
126 It is not needed and should not stop execution
127 */
128 BlockSignals(True, SIGPIPE);
129}
130
131#if 0
132/*****************************************************
133remove redundent stuff from a filename
134*******************************************************/
135void clean_fname(char *name)
136{
137 char *p, *p2;
138 int l;
139 int modified = 1;
140
141 if (!name) return;
142
143 while (modified) {
144 modified = 0;
145
146 if ((p=strstr(name,"/./"))) {
147 modified = 1;
148 while (*p) {
149 p[0] = p[2];
150 p++;
151 }
152 }
153
154 if ((p=strstr(name,"//"))) {
155 modified = 1;
156 while (*p) {
157 p[0] = p[1];
158 p++;
159 }
160 }
161
162 if (strcmp(name,"/../")==0) {
163 modified = 1;
164 name[1] = 0;
165 }
166
167 if ((p=strstr(name,"/../"))) {
168 modified = 1;
169 for (p2=(p>name?p-1:p);p2>name;p2--) {
170 if (p2[0] == '/') break;
171 }
172 while (*p2) {
173 p2[0] = p2[3];
174 p2++;
175 }
176 }
177
178 if (strcmp(name,"/..")==0) {
179 modified = 1;
180 name[1] = 0;
181 }
182
183 l = strlen(name);
184 p = l>=3?(name+l-3):name;
185 if (strcmp(p,"/..")==0) {
186 modified = 1;
187 for (p2=p-1;p2>name;p2--) {
188 if (p2[0] == '/') break;
189 }
190 if (p2==name) {
191 p[0] = '/';
192 p[1] = 0;
193 } else {
194 p2[0] = 0;
195 }
196 }
197
198 l = strlen(name);
199 p = l>=2?(name+l-2):name;
200 if (strcmp(p,"/.")==0) {
201 if (p == name) {
202 p[1] = 0;
203 } else {
204 p[0] = 0;
205 }
206 }
207
208 if (strncmp(p=name,"./",2) == 0) {
209 modified = 1;
210 do {
211 p[0] = p[2];
212 } while (*p++);
213 }
214
215 l = strlen(p=name);
216 if (l > 1 && p[l-1] == '/') {
217 modified = 1;
218 p[l-1] = 0;
219 }
220 }
221}
222#endif
223
224/*****************************************************
225return a connection to a server
226loosely based on do_connect() from libsmb/clidfs.c
227*******************************************************/
228int _System smbwrp_connect( Resource* pRes, cli_state ** cli)
229{
230 smbwrp_server * srv = &pRes->srv;
231 char * server = srv->server_name;
232 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
233 char * workgroup = srv->workgroup;
234 struct nmb_name called, calling;
235 char *p, *server_n = server;
236 struct cli_state * c;
237 char* dev_type;
238 int loginerror = 0;
239 NTSTATUS status;
240 int max_protocol = lp__client_max_protocol();
241 int port = 0; //NBT_SMB_PORT;
242 int name_type= 0x20;
243 int flags = 0;
244 enum protocol_types protocol;
245 const char *name = NULL;
246
247 if (!pRes->krb5support)
248 debuglocal(1,"Connecting to \\\\%s:*********@%s:%s\\%s. Master %s:%d\n", srv->username, workgroup, server, share, srv->master, srv->ifmastergroup);
249 else
250 debuglocal(1,"Connecting to \\\\%s:%s\\%s using kerberos authentication. Master %s:%d\n", workgroup, server, share, srv->master, srv->ifmastergroup);
251
252 if (pRes->krb5support) {
253 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
254 }
255
256 status = cli_connect_nb(
257 server, NULL, port, name_type, NULL,
258 SMB_SIGNING_DEFAULT, flags, &c);
259
260 if (!NT_STATUS_IS_OK(status)) {
261 debuglocal(4,"Connection to %s failed (Error %s)\n",
262 server,
263 nt_errstr(status));
264 return 3;
265 }
266
267 if (max_protocol == PROTOCOL_DEFAULT) {
268 max_protocol = PROTOCOL_LATEST;
269 }
270 DEBUG(4,(" session request ok, c->timeout = %d\n",c->timeout));
271
272 status = smbXcli_negprot(c->conn, c->timeout,
273 lp_client_min_protocol(),
274 max_protocol);
275
276 if (!NT_STATUS_IS_OK(status)) {
277 debuglocal(4,"protocol negotiation failed: %s\n",
278 nt_errstr(status));
279 cli_shutdown(c);
280 return status;
281 }
282
283 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
284 srv->password, strlen(srv->password),
285 srv->password, strlen(srv->password),
286 workgroup))) {
287 debuglocal(4,"%s/******** login failed\n", srv->username);
288 loginerror = 1; // save the login error
289
290 /* try an anonymous login if it failed */
291
292 /* If a password was not supplied then
293 * try again with a null username. */
294 if (srv->password[0] || !srv->username[0] ||
295 pRes->krb5support ||
296 !NT_STATUS_IS_OK(status = cli_session_setup(c, "",
297 "", 0,
298 "", 0,
299 workgroup))) {
300 debuglocal(1,"session setup failed: %s\n",
301 nt_errstr(status));
302
303 if ((NT_STATUS_EQUAL(status,
304 NT_STATUS_MORE_PROCESSING_REQUIRED)) ||
305 NT_STATUS_EQUAL(status,
306 NT_STATUS_INTERNAL_ERROR)){
307 debuglocal(4,"did you forget to run kinit?\n");
308 } else
309 debuglocal(4,"Anonymous login failed\n");
310
311 cli_shutdown(c);
312 return 6;
313 }
314 debuglocal(4,"Anonymous login successful\n");
315 }
316
317 if (!NT_STATUS_IS_OK(status)) {
318 debuglocal(4,"cli_init_creds() failed\n");
319 cli_shutdown(c);
320 // if loginerror is != 0 means normal login failed, but anonymous login worked
321 if (loginerror !=0)
322 return 6;
323 else
324 return 7;
325 }
326
327 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
328
329 // YD ticket:58 we need to check resource type to avoid connecting to printers.
330 // dev type is set to IPC for IPC$, A: for everything else (printers use LPT1:)
331 if (!strcmp( share, "IPC$"))
332 dev_type = "IPC";
333 else
334 dev_type = "A:";
335
336 if (!NT_STATUS_IS_OK(cli_tcon_andx(c, share, dev_type,
337 srv->password, strlen(srv->password)+1))) {
338 cli_shutdown(c);
339 // if loginerror is != 0 means normal login failed, but anonymous login worked
340 if (loginerror !=0)
341 return 6;
342 else
343 return 7;
344 }
345
346 debuglocal(4," tconx ok.\n");
347
348 // save cli_state pointer
349 *cli = c;
350
351 return 0;
352}
353
354/*****************************************************
355close a connection to a server
356*******************************************************/
357void _System smbwrp_disconnect( Resource* pRes, cli_state * cli)
358{
359 if (pRes && cli)
360 {
361 // this call will free all buffers, close handles and free cli mem
362 cli_shutdown( cli);
363 }
364}
365
366
367
368/*****************************************************
369a wrapper for open()
370*******************************************************/
371int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
372{
373 uint16_t fd = 0;
374
375 if (!cli || !file || !*file->fname)
376 {
377 return maperror(EINVAL);
378 }
379 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
380 {
381 file->denymode = DENY_NONE;
382 }
383
384 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
385 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
386 {
387 return os2cli_errno(cli);
388 }
389 file->fd = fd;
390 file->updatetime = 0;
391 file->offset = 0;
392 return 0;
393}
394
395/*****************************************************
396a wrapper for read()
397*******************************************************/
398int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
399{
400 int ret;
401
402 if (!cli || !file || !buf || !result)
403 {
404 return maperror(EINVAL);
405 }
406 size_t nread;
407 *result = 0;
408 ret = cli_read(cli, file->fd, buf, file->offset, count, &nread);
409 if (ret == -1)
410 {
411 debuglocal(4," smbwrp_read - cli_read ret = %d\n",ret);
412 return os2cli_errno(cli);
413 }
414
415 file->offset += nread;
416 *result = nread;
417 debuglocal(4," smbwrp_read successful, nread = %d, ret = %d\n",nread,ret);
418 return 0;
419}
420
421
422
423/*****************************************************
424a wrapper for write()
425*******************************************************/
426int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
427{
428 NTSTATUS status;
429 size_t ret;
430
431 if (!cli || !file || !buf || !result)
432 {
433 return maperror(EINVAL);
434 }
435
436 *result = 0;
437//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
438 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret);
439 if (!NT_STATUS_IS_OK(status)) {
440 return os2cli_errno(cli);
441 }
442
443 file->updatetime = 1;
444 file->offset += ret;
445 *result = ret;
446 return 0;
447}
448
449/*****************************************************
450a wrapper for close()
451*******************************************************/
452int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
453{
454 int rc = 0;
455 if (!cli || !file)
456 {
457 return maperror(EINVAL);
458 }
459
460 debuglocal(4,"smpwrp_close updatetime: %d\n", file->updatetime);
461
462 if (file->updatetime == 1)
463 {
464 file->mtime = time(NULL);
465 debuglocal(4,"cli_close new mtime %lu\n", file->mtime);
466 }
467
468 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
469 {
470 rc = os2cli_errno(cli);
471 }
472
473 if (!rc && (file->openattr || file->mtime || file->ctime))
474 {
475 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime);
476 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))
477 {
478 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli));
479 //rc = os2cli_errno(cli);
480 }
481 }
482
483 file->openattr = 0;
484 file->mtime = 0;
485 file->ctime = 0;
486 file->updatetime = 0;
487 file->fd = -1;
488 file->offset = 0;
489 *file->fname = 0;
490 return rc;
491}
492
493int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
494{
495 int rc = 0;
496 if (!cli || !file)
497 {
498 return maperror(EINVAL);
499 }
500
501 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize);
502 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize)))
503 {
504 if (newsize)
505 {
506 rc = os2cli_errno(cli);
507 }
508
509 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
510 {
511 return os2cli_errno(cli);
512 }
513 uint16_t fd = 0;
514 file->fd = -1;
515 file->offset = 0;
516 file->openmode &= ~(O_CREAT | O_EXCL);
517 file->openmode |= O_TRUNC;
518 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
519 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
520 {
521 return os2cli_errno(cli);
522 }
523 file->fd = fd;
524 }
525 return 0;
526}
527
528/*****************************************************
529a wrapper for rename()
530*******************************************************/
531int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
532{
533 if (!cli || !oldname || !newname)
534 {
535 return maperror(EINVAL);
536 }
537
538 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
539 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
540 {
541 return os2cli_errno(cli);
542 }
543 return 0;
544}
545
546
547/*****************************************************
548a wrapper for chmod()
549*******************************************************/
550int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
551{
552 if (!cli || !finfo || !*finfo->fname)
553 {
554 return maperror(EINVAL);
555 }
556
557debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
558 // we already have gmt time, so no need to add timezone
559 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
560 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
561 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
562 {
563 return os2cli_errno(cli);
564 }
565 return 0;
566}
567
568/*****************************************************
569a wrapper for unlink()
570*******************************************************/
571int _System smbwrp_unlink(cli_state * cli, const char *fname)
572{
573 if (!cli || !fname)
574 {
575 return maperror(EINVAL);
576 }
577#if 0
578 if (strncmp(cli->dev, "LPT", 3) == 0)
579 {
580 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
581 if (job == -1)
582 {
583 goto failed;
584 }
585 if (cli_printjob_del(cli, job) != 0)
586 {
587 goto failed;
588 }
589 } else
590#endif
591 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
592 {
593 return os2cli_errno(cli);
594 }
595 return 0;
596}
597
598/*****************************************************
599a wrapper for lseek()
600*******************************************************/
601int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
602{
603 off_t size;
604 if (!cli || !file)
605 {
606 return maperror(EINVAL);
607 }
608
609 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
610
611 switch (whence) {
612 case SEEK_SET:
613 if (offset < 0)
614 {
615 return maperror(EINVAL);
616 }
617 file->offset = offset;
618 break;
619 case SEEK_CUR:
620 file->offset += offset;
621 break;
622 case SEEK_END:
623 if (offset > 0)
624 {
625 return maperror(EINVAL);
626 }
627 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
628 NULL, &size, NULL, NULL, NULL,
629 NULL, NULL)) &&
630 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
631 NULL, &size, NULL, NULL, NULL)))
632 {
633 return os2cli_errno(cli);
634 }
635 file->offset = size + offset;
636 break;
637 default: return maperror(EINVAL);
638 }
639
640 return 0;
641}
642
643/*****************************************************
644try to do a QPATHINFO and if that fails then do a getatr
645this is needed because win95 sometimes refuses the qpathinfo
646*******************************************************/
647int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
648{
649 SMB_INO_T ino = 0;
650 struct timespec ctime;
651 struct timespec mtime;
652 struct timespec atime;
653
654 if (!cli || !finfo || !*finfo->fname)
655 {
656 return maperror(EINVAL);
657 }
658 debuglocal(4,"getattr %d %d <%s>\n", smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2, smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS, finfo->fname);
659
660 if (NT_STATUS_IS_OK(cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
661 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
662 {
663 finfo->attr &= 0x7F;
664 finfo->ctime = convert_timespec_to_time_t(ctime);
665 finfo->atime = convert_timespec_to_time_t(atime);
666 finfo->mtime = convert_timespec_to_time_t(mtime);
667 return 0;
668 }
669
670#if 0 // cli->fd not available in Samba 4.x
671 if (cli->fd == -1)
672 {
673 /* fd == -1 means the connection is broken */
674 return maperror(ENOTCONN);
675 }
676#endif
677
678 debuglocal(4, "smbwrp_getattr, calling cli_qpathinfo3\n");
679 if (NT_STATUS_IS_OK(cli_qpathinfo3(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
680 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
681 {
682 finfo->attr &= 0x7F;
683 finfo->ctime = convert_timespec_to_time_t(ctime);
684 finfo->atime = convert_timespec_to_time_t(atime);
685 finfo->mtime = convert_timespec_to_time_t(mtime);
686 return 0;
687 }
688
689 /* If the path is not on a share (it is a workgroup or a server),
690 * then cli_qpathinfo2 obviously fails. Return some fake information
691 * about the directory.
692 */
693 if ( *srv->server_name == 0
694 || (strcmp(cli->dev,"IPC") == 0)
695 || *srv->share_name == 0
696 || (stricmp(srv->share_name,"IPC$") == 0)
697 || (strncmp(cli->dev,"LPT",3) == 0)
698 )
699 {
700 debuglocal(4,"getattr not a share.\n");
701 *(time_t *)&finfo->ctime = time (NULL);
702 *(time_t *)&finfo->atime = time (NULL);
703 *(time_t *)&finfo->mtime = time (NULL);
704 finfo->size = 0;
705 finfo->easize = 0;
706 finfo->attr = aDIR;
707 return 0;
708 }
709
710 /* if this is NT then don't bother with the getatr */
711 if (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS/* && !(smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2)*/)
712 {
713 int ret = cli_errno(cli);
714 // cli_qpathinfo* reports EINVAL when path of given file not exists
715 // thus there is no real situation when EINVAL should be returned to
716 // client at this point, we just replace it to ENOTDIR
717 if (ret == EINVAL)
718 {
719 ret = ENOTDIR;
720 }
721 return maperror(ret);
722 }
723
724 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
725 {
726//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
727 finfo->mtime -= get_time_zone(finfo->mtime);
728 finfo->atime = finfo->atime; //was mtime
729 finfo->ctime = finfo->ctime; //was mtime
730 return 0;
731 }
732 return os2cli_errno(cli);
733}
734
735/*****************************************************
736try to do a QPATHINFO and if that fails then do a getatr
737this is needed because win95 sometimes refuses the qpathinfo
738*******************************************************/
739int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
740{
741 struct timespec ctime;
742 struct timespec mtime;
743 struct timespec atime;
744 SMB_INO_T ino = 0;
745
746 if (!cli || !file || !finfo)
747 {
748 return maperror(EINVAL);
749 }
750
751 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
752 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
753 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL,
754 &ino)))
755 {
756 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
757 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
758 {
759 return os2cli_errno(cli);
760 }
761 else
762 {
763 finfo->ctime -= get_time_zone(finfo->ctime);
764 finfo->atime -= get_time_zone(finfo->atime);
765 finfo->mtime -= get_time_zone(finfo->mtime);
766 }
767 }
768 else
769 {
770 finfo->ctime = convert_timespec_to_time_t(ctime);
771 finfo->atime = convert_timespec_to_time_t(atime);
772 finfo->mtime = convert_timespec_to_time_t(mtime);
773 }
774
775 return 0;
776}
777
778// =============================DIRECTORY ROUTINES============================
779
780/*****************************************************
781add a entry to a directory listing
782*******************************************************/
783static NTSTATUS smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
784{
785 if (state && finfo)
786 {
787 filelist_state * st = (filelist_state *)state;
788 char fullname[ _MAX_PATH] = {0};
789 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
790 memcpy(&st->finfo, finfo, sizeof(st->finfo));
791 strncpy(fullname, st->dir, strlen(st->dir));
792 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
793 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
794 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
795 }
796}
797
798static void smbwrp_special_add(const char * name, void * state)
799{
800 smbwrp_fileinfo finfo = {0};
801
802 if (!name)
803 {
804 return;
805 }
806
807 ZERO_STRUCT(finfo);
808
809 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
810 finfo.attr = aRONLY | aDIR;
811
812 smbwrp_dir_add("", &finfo, NULL, state);
813}
814
815static NTSTATUS smbwrp_printjob_add(struct print_job_info *job, void * state)
816{
817 smbwrp_fileinfo finfo = {0};
818
819 ZERO_STRUCT(finfo);
820
821//printf("Printjob <%s>\n", job->name);
822
823 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
824 finfo.mtime = job->t - get_time_zone(job->t);
825 finfo.atime = finfo.atime; //was mtime
826 finfo.ctime = finfo.ctime; //was mtime
827 finfo.attr = aRONLY;
828 finfo.size = job->size;
829
830 smbwrp_dir_add("", &finfo, NULL, state);
831}
832
833static void smbwrp_share_add(const char *share, uint32_t type,
834 const char *comment, void *state)
835{
836 smbwrp_fileinfo finfo = {0};
837
838 // strip administrative names and printers from list
839 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
840
841 ZERO_STRUCT(finfo);
842
843 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
844 finfo.attr = aRONLY | aDIR;
845
846 smbwrp_dir_add("", &finfo, NULL, state);
847}
848
849/****************************************************************************
850 Do a directory listing, calling fn on each file found.
851 Modified from cli_list
852****************************************************************************/
853static int list_files(struct cli_state *cli, const char *mask, uint16_t attribute,
854 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
855 void *), void *state)
856{
857 TALLOC_CTX *frame = talloc_stackframe();
858 struct event_context *ev;
859 struct tevent_req *req;
860 NTSTATUS status = NT_STATUS_NO_MEMORY;
861 struct file_info *finfo;
862 size_t i, num_finfo;
863 uint16_t info_level;
864 void *dircachectx = NULL;
865 smbwrp_fileinfo wrpfinfo;
866
867 /* Try to get the listing from cache. */
868 if (dircache_list_files(fn, state, &num_finfo))
869 {
870 /* Got from cache. */
871 return(num_finfo);
872 }
873
874 if (smbXcli_conn_has_async_calls(cli->conn)) {
875 /*
876 * Can't use sync call while an async call is in flight
877 */
878 status = NT_STATUS_INVALID_PARAMETER;
879 goto fail;
880 }
881 ev = samba_tevent_context_init(frame);
882 if (ev == NULL) {
883 goto fail;
884 }
885
886 info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
887 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
888
889 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
890
891 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
892 if (req == NULL) {
893 goto fail;
894 }
895 if (!tevent_req_poll(req, ev)) {
896 status = map_nt_error_from_unix(errno);
897 goto fail;
898 }
899
900 status = cli_list_recv(req, frame, &finfo, &num_finfo);
901 if (!NT_STATUS_IS_OK(status)) {
902 goto fail;
903 }
904
905 dircachectx = dircache_write_begin(state, num_finfo);
906
907 debuglocal(4,"list_files: got %d files\n", num_finfo);
908
909
910 for (i=0; i<num_finfo; i++) {
911 //as samba and this client have different finfo, we need to convert
912 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
913 wrpfinfo.size = finfo[i].size;
914 wrpfinfo.attr = finfo[i].mode;
915 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
916 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
917 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
918 wrpfinfo.easize = finfo[i].easize;
919 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
920
921 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
922 // Also add the entry to the cache.
923 dircache_write_entry(dircachectx, &wrpfinfo);
924 }
925
926 dircache_write_end(dircachectx);
927 fail:
928 TALLOC_FREE(frame);
929 return num_finfo;
930}
931
932/*****************************************************
933open a directory on the server
934*******************************************************/
935int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
936{
937 if (!srv || !cli || !state || !*state->mask)
938 {
939 return maperror(EINVAL);
940 }
941 debuglocal(1,"Filelist <%s> on master <%s> wgrp <%s> server <%s> share <%s> clidev <%s>\n", state->mask, srv->master, srv->workgroup, srv->server_name, srv->share_name, cli->dev);
942 if (*srv->workgroup == 0 && *srv->server_name == 0)
943 {
944 smbwrp_special_add(".", state);
945 smbwrp_special_add("..", state);
946 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
947 smbwrp_share_add, state);
948 } else
949 if (*srv->server_name == 0)
950 {
951 smbwrp_special_add(".", state);
952 smbwrp_special_add("..", state);
953
954 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
955 smbwrp_share_add, state);
956 } else
957 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
958 {
959 smbwrp_special_add(".", state);
960 smbwrp_special_add("..", state);
961
962 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
963 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
964 {
965 return os2cli_errno(cli);
966 }
967 } else
968 if (strncmp(cli->dev,"LPT",3) == 0)
969 {
970 smbwrp_special_add(".", state);
971 smbwrp_special_add("..", state);
972 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
973 {
974 return os2cli_errno(cli);
975 }
976 }
977 else
978 {
979 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
980 smbwrp_dir_add, state) < 0)
981 {
982 return os2cli_errno(cli);
983 }
984 }
985
986 return 0;
987}
988
989/*****************************************************
990a wrapper for chdir()
991*******************************************************/
992int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
993{
994 unsigned short mode = aDIR;
995 smbwrp_fileinfo finfo = {0};
996 if (!cli || !fname)
997 {
998 return maperror(EINVAL);
999 }
1000
1001 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1002 if (smbwrp_getattr(srv, cli, &finfo))
1003 {
1004 return os2cli_errno(cli);
1005 }
1006
1007 if (!(finfo.attr & aDIR)) {
1008 return maperror(ENOTDIR);
1009 }
1010
1011 return 0;
1012}
1013
1014
1015/*****************************************************
1016a wrapper for mkdir()
1017*******************************************************/
1018int _System smbwrp_mkdir(cli_state * cli, char *fname)
1019{
1020 if (!cli || !fname)
1021 {
1022 return maperror(EINVAL);
1023 }
1024
1025 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1026 {
1027 return os2cli_errno(cli);
1028 }
1029 return 0;
1030}
1031
1032/*****************************************************
1033a wrapper for rmdir()
1034*******************************************************/
1035int _System smbwrp_rmdir(cli_state * cli, char *fname)
1036{
1037 if (!cli || !fname)
1038 {
1039 return maperror(EINVAL);
1040 }
1041
1042 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1043 {
1044 return os2cli_errno(cli);
1045 }
1046 return 0;
1047}
1048
1049/*****************************************************
1050set EA for a path
1051*******************************************************/
1052int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1053{
1054 if (!cli || !fname || !name)
1055 {
1056 return maperror(EINVAL);
1057 }
1058 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1059 {
1060 return os2cli_errno(cli);
1061 }
1062 return 0;
1063}
1064
1065/*****************************************************
1066set EA for a file
1067*******************************************************/
1068int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1069{
1070 if (!cli || !file || !name)
1071 {
1072 return maperror(EINVAL);
1073 }
1074 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1075 {
1076 return os2cli_errno(cli);
1077 }
1078 return 0;
1079}
1080
1081
1082#pragma pack(1)
1083typedef struct _FEA /* fea */
1084{
1085 unsigned char fEA; /* flags */
1086 unsigned char cbName; /* name length not including NULL */
1087 unsigned short cbValue; /* value length */
1088} FEA;
1089
1090typedef struct _FEALIST /* feal */
1091{
1092 unsigned long cbList; /* total bytes of structure including full list */
1093 FEA list[1]; /* variable length FEA structures */
1094} FEALIST;
1095#pragma pack()
1096
1097static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1098{
1099 int fnum, i;
1100 int gotsize = sizeof(unsigned long);
1101 size_t num_eas;
1102 struct ea_struct *ea_list = NULL;
1103 TALLOC_CTX *mem_ctx;
1104 FEA * p;
1105 FEALIST * pfealist;
1106 char * q;
1107
1108 mem_ctx = talloc_init("%d: ealist", _gettid());
1109 pfealist = (FEALIST *)buffer;
1110 pfealist->cbList = 0;
1111
1112 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1113 {
1114 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1115 talloc_destroy(mem_ctx);
1116 return os2cli_errno(cli);
1117 }
1118
1119 debuglocal(4,"num_eas = %d\n", num_eas);
1120
1121 // we will count that os/2 max EA size for file is 64kb
1122 p = pfealist->list;
1123 for (i = 0; i < num_eas; i++)
1124 {
1125 int namelen = strlen(ea_list[i].name);
1126 debuglocal(4, "%d Got EA <%s> with namelen %d, size %d. Gross %d. Buf %d\n", i, ea_list[i].name, namelen, ea_list[i].value.length, gotsize, size);
1127 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1128 {
1129 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1130 continue;
1131 }
1132 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1133 if (size >= gotsize)
1134 {
1135 p->fEA = 0;
1136 p->cbName = namelen;
1137 p->cbValue = ea_list[i].value.length;
1138 q = (char *)(p + 1);
1139 strncpy(q, ea_list[i].name, namelen + 1);
1140 q += namelen + 1;
1141 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1142 p = (FEA *)(q + ea_list[i].value.length);
1143 }
1144 }
1145 pfealist->cbList = gotsize;
1146 debuglocal(4,"ret size = %d\n", gotsize);
1147
1148 talloc_destroy(mem_ctx);
1149 return 0;
1150}
1151
1152/*****************************************************
1153lists EA of a path
1154*******************************************************/
1155int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1156{
1157 if (!cli || !fname || !buffer)
1158 {
1159 return maperror(EINVAL);
1160 }
1161
1162 debuglocal(4,"EALIst for <%s>\n", fname);
1163 return unilistea(cli, fname, buffer, size);
1164}
1165
1166/*****************************************************
1167lists EA of a file
1168*******************************************************/
1169int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1170{
1171 if (!cli || !file || !buffer)
1172 {
1173 return maperror(EINVAL);
1174 }
1175
1176 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1177 return unilistea(cli, file->fname, buffer, size);
1178}
1179
1180/****************************************************************************
1181Check the space on a device.
1182****************************************************************************/
1183int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1184{
1185 int total, bsize, avail;
1186
1187 if (!cli || !pfsa)
1188 {
1189 return maperror(EINVAL);
1190 }
1191
1192 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1193 {
1194 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1195 return os2cli_errno(cli);
1196 }
1197
1198 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1199 total, bsize, avail);
1200
1201 // YD currently Samba return it in MB!
1202 pfsa->cSectorUnit = 1;
1203 if (bsize >= 65536)
1204 {
1205 pfsa->cUnit = total*1024;
1206 pfsa->cUnitAvail = avail*1024;
1207 pfsa->cbSector = bsize/1024;
1208 }
1209 else
1210 {
1211 pfsa->cUnit = total;
1212 pfsa->cUnitAvail = avail;
1213 pfsa->cbSector = bsize;
1214 }
1215
1216 return 0;
1217}
1218
Note: See TracBrowser for help on using the repository browser.