00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 #define TICKET_CC_DIR "/tmp"
00027 #define CC_PREFIX "krb5cc_"
00028 #define CC_MAX_FILE_LEN 24
00029 #define CC_MAX_FILE_PATH_LEN (sizeof(TICKET_CC_DIR)-1)+ CC_MAX_FILE_LEN+2
00030 #define OVERWRITE 1
00031 #define KRB5CCNAME "KRB5CCNAME"
00032 #define MAX_RETRY_CONNECT 3
00033
00034
00035
00036
00037
00038
00039 extern BOOL in_client;
00040
00041
00042
00043
00044
00045
00046 static void list_devices(void);
00047 static struct cli_state *smb_complete_connection(const char *, const char *,int , const char *, const char *, const char *, const char *, int);
00048 static struct cli_state *smb_connect(const char *, const char *, int, const char *, const char *, const char *, const char *);
00049 static int smb_print(struct cli_state *, char *, FILE *);
00050 static char * uri_unescape_alloc(const char *);
00051
00052
00053
00054
00055
00056
00057 int
00058 main(int argc,
00059 char *argv[])
00060 {
00061 int i;
00062 int copies;
00063 int port;
00064 char uri[1024],
00065 *sep,
00066 *tmp, *tmp2,
00067 *password;
00068 char *username,
00069 *server,
00070 *printer;
00071 const char *workgroup;
00072 FILE *fp;
00073 int status=0;
00074 struct cli_state *cli;
00075 char null_str[1];
00076 int tries = 0;
00077 const char *dev_uri;
00078
00079 null_str[0] = '\0';
00080
00081
00082 if (argc > 2 && strncmp(argv[0],"smb://", 6) && !strncmp(argv[1],"smb://", 6)) {
00083 argv++;
00084 argc--;
00085 }
00086
00087 if (argc == 1)
00088 {
00089
00090
00091
00092
00093
00094
00095
00096 list_devices();
00097 return (0);
00098 }
00099
00100 if (argc < 6 || argc > 7)
00101 {
00102 fprintf(stderr, "Usage: %s [DEVICE_URI] job-id user title copies options [file]\n",
00103 argv[0]);
00104 fputs(" The DEVICE_URI environment variable can also contain the\n", stderr);
00105 fputs(" destination printer:\n", stderr);
00106 fputs("\n", stderr);
00107 fputs(" smb://[username:password@][workgroup/]server[:port]/printer\n", stderr);
00108 return (1);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 if (argc == 6)
00118 {
00119
00120
00121
00122
00123 fp = stdin;
00124 copies = 1;
00125 }
00126 else if ((fp = fopen(argv[6], "rb")) == NULL)
00127 {
00128 perror("ERROR: Unable to open print file");
00129 return (1);
00130 }
00131 else
00132 copies = atoi(argv[4]);
00133
00134
00135
00136
00137
00138 dev_uri = getenv("DEVICE_URI");
00139 if (dev_uri)
00140 strncpy(uri, dev_uri, sizeof(uri) - 1);
00141 else if (strncmp(argv[0], "smb://", 6) == 0)
00142 strncpy(uri, argv[0], sizeof(uri) - 1);
00143 else
00144 {
00145 fputs("ERROR: No device URI found in DEVICE_URI environment variable or argv[0] !\n", stderr);
00146 return (1);
00147 }
00148
00149 uri[sizeof(uri) - 1] = '\0';
00150
00151
00152
00153
00154
00155 if ((sep = strrchr_m(uri, '@')) != NULL)
00156 {
00157 tmp = uri + 6;
00158 *sep++ = '\0';
00159
00160
00161
00162 server = sep;
00163
00164
00165
00166
00167
00168 if ((tmp2 = strchr_m(tmp, ':')) != NULL) {
00169 *tmp2++ = '\0';
00170 password = uri_unescape_alloc(tmp2);
00171 } else {
00172 password = null_str;
00173 }
00174 username = uri_unescape_alloc(tmp);
00175 }
00176 else
00177 {
00178 username = "dummy";
00179 password = null_str;
00180 server = uri + 6;
00181 }
00182
00183 tmp = server;
00184
00185 if ((sep = strchr_m(tmp, '/')) == NULL)
00186 {
00187 fputs("ERROR: Bad URI - need printer name!\n", stderr);
00188 return (1);
00189 }
00190
00191 *sep++ = '\0';
00192 tmp2 = sep;
00193
00194 if ((sep = strchr_m(tmp2, '/')) != NULL)
00195 {
00196
00197
00198
00199
00200 *sep++ = '\0';
00201
00202 workgroup = uri_unescape_alloc(tmp);
00203 server = uri_unescape_alloc(tmp2);
00204 printer = uri_unescape_alloc(sep);
00205 }
00206 else {
00207 workgroup = NULL;
00208 server = uri_unescape_alloc(tmp);
00209 printer = uri_unescape_alloc(tmp2);
00210 }
00211
00212 if ((sep = strrchr_m(server, ':')) != NULL)
00213 {
00214 *sep++ = '\0';
00215
00216 port=atoi(sep);
00217 }
00218 else
00219 port=0;
00220
00221
00222
00223
00224
00225
00226 setup_logging("smbspool", True);
00227
00228 in_client = True;
00229
00230 load_case_tables();
00231
00232 if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
00233 {
00234 fprintf(stderr, "ERROR: Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
00235 return (1);
00236 }
00237
00238 if (workgroup == NULL)
00239 workgroup = lp_workgroup();
00240
00241 load_interfaces();
00242
00243 do
00244 {
00245 if ((cli = smb_connect(workgroup, server, port, printer, username, password, argv[2])) == NULL)
00246 {
00247 if (getenv("CLASS") == NULL)
00248 {
00249 fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...\n");
00250 sleep (60);
00251 tries++;
00252 }
00253 else
00254 {
00255 fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...\n");
00256 return (1);
00257 }
00258 }
00259 }
00260 while ((cli == NULL) && (tries < MAX_RETRY_CONNECT));
00261
00262 if (cli == NULL) {
00263 fprintf(stderr, "ERROR: Unable to connect to CIFS host after (tried %d times)\n", tries);
00264 return (1);
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 if (argc < 7)
00275 CatchSignal(SIGTERM, SIG_IGN);
00276
00277
00278
00279
00280
00281 for (i = 0; i < copies; i ++)
00282 if ((status = smb_print(cli, argv[3] , fp)) != 0)
00283 break;
00284
00285 cli_shutdown(cli);
00286
00287
00288
00289
00290
00291 return (status);
00292 }
00293
00294
00295
00296
00297
00298
00299 static void
00300 list_devices(void)
00301 {
00302
00303
00304
00305
00306 puts("network smb \"Unknown\" \"Windows Printer via SAMBA\"");
00307 }
00308
00309
00310
00311
00312
00313
00314 static
00315 char * get_ticket_cache( uid_t uid )
00316 {
00317 char *ticket_file = NULL;
00318 SMB_STRUCT_DIR *tcdir;
00319 SMB_STRUCT_DIRENT *dirent;
00320 char *filename = NULL;
00321 SMB_STRUCT_STAT buf;
00322 char user_cache_prefix[CC_MAX_FILE_LEN];
00323 char file_path[CC_MAX_FILE_PATH_LEN];
00324 time_t t = 0;
00325
00326 snprintf(user_cache_prefix, CC_MAX_FILE_LEN, "%s%d", CC_PREFIX, uid );
00327 tcdir = sys_opendir( TICKET_CC_DIR );
00328 if ( tcdir == NULL )
00329 return NULL;
00330
00331 while ( (dirent = sys_readdir( tcdir ) ) )
00332 {
00333 filename = dirent->d_name;
00334 snprintf(file_path, CC_MAX_FILE_PATH_LEN,"%s/%s", TICKET_CC_DIR, filename);
00335 if (sys_stat(file_path, &buf) == 0 )
00336 {
00337 if ( ( buf.st_uid == uid ) && ( S_ISREG(buf.st_mode) ) )
00338 {
00339
00340
00341
00342
00343
00344 if ( strstr( filename, user_cache_prefix ) )
00345 {
00346 if ( buf.st_mtime > t )
00347 {
00348
00349
00350
00351 free(ticket_file);
00352 ticket_file=SMB_STRDUP(file_path);
00353 t = buf.st_mtime;
00354 }
00355 }
00356 }
00357 }
00358 }
00359
00360 sys_closedir(tcdir);
00361
00362 if ( ticket_file == NULL )
00363 {
00364
00365 fprintf(stderr, "ERROR: No ticket cache found for userid=%d\n", uid);
00366 return NULL;
00367 }
00368
00369 return ticket_file;
00370 }
00371
00372 static struct cli_state
00373 *smb_complete_connection(const char *myname,
00374 const char *server,
00375 int port,
00376 const char *username,
00377 const char *password,
00378 const char *workgroup,
00379 const char *share,
00380 int flags)
00381 {
00382 struct cli_state *cli;
00383 NTSTATUS nt_status;
00384
00385
00386 nt_status = cli_start_connection( &cli, myname, server, NULL, port,
00387 Undefined, flags, NULL);
00388 if (!NT_STATUS_IS_OK(nt_status))
00389 {
00390 return NULL;
00391 }
00392
00393
00394
00395 if (!password) {
00396 return NULL;
00397 }
00398
00399 if ( (username) && (*username) &&
00400 (strlen(password) == 0 ) &&
00401 (cli->use_kerberos) )
00402 {
00403
00404 struct passwd *pw;
00405 char *cache_file;
00406
00407
00408 if ( !(pw = sys_getpwnam(username)) ) {
00409 fprintf(stderr,"ERROR Can not get %s uid\n", username);
00410 cli_shutdown(cli);
00411 return NULL;
00412 }
00413
00414
00415
00416
00417
00418 cache_file = get_ticket_cache( pw->pw_uid );
00419 if ( cache_file == NULL )
00420 {
00421 fprintf(stderr, "ERROR: Can not get the ticket cache for %s\n", username);
00422 cli_shutdown(cli);
00423 return NULL;
00424 }
00425
00426 if ( setenv(KRB5CCNAME, cache_file, OVERWRITE) < 0 )
00427 {
00428 fprintf(stderr, "ERROR: Can not add KRB5CCNAME to the environment");
00429 cli_shutdown(cli);
00430 free(cache_file);
00431 return NULL;
00432 }
00433 free(cache_file);
00434
00435
00436
00437
00438
00439 setuid(pw->pw_uid);
00440
00441 }
00442
00443
00444 if (!NT_STATUS_IS_OK(cli_session_setup(cli, username,
00445 password, strlen(password)+1,
00446 password, strlen(password)+1,
00447 workgroup)))
00448 {
00449 fprintf(stderr,"ERROR: Session setup failed: %s\n", cli_errstr(cli));
00450 if (NT_STATUS_V(cli_nt_error(cli)) ==
00451 NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
00452 {
00453 fprintf(stderr, "did you forget to run kinit?\n");
00454 }
00455 cli_shutdown(cli);
00456
00457 return NULL;
00458 }
00459
00460 if (!cli_send_tconX(cli, share, "?????", password, strlen(password)+1))
00461 {
00462 fprintf(stderr, "ERROR: Tree connect failed (%s)\n", cli_errstr(cli));
00463 cli_shutdown(cli);
00464 return NULL;
00465 }
00466
00467 return cli;
00468 }
00469
00470
00471
00472
00473
00474 static struct cli_state *
00475 smb_connect(const char *workgroup,
00476 const char *server,
00477 const int port,
00478 const char *share,
00479 const char *username,
00480 const char *password,
00481 const char *jobusername)
00482 {
00483 struct cli_state *cli;
00484 pstring myname;
00485 struct passwd *pwd;
00486
00487
00488
00489
00490
00491 get_myname(myname);
00492
00493
00494
00495
00496 if ( username && *username )
00497 {
00498 cli = smb_complete_connection(myname, server, port, username,
00499 password, workgroup, share, 0 );
00500 if (cli)
00501 return cli;
00502 }
00503
00504
00505
00506
00507 cli = smb_complete_connection(myname, server, port, jobusername, "",
00508 workgroup, share,
00509 CLI_FULL_CONNECTION_USE_KERBEROS );
00510
00511 if (cli ) { return cli; }
00512
00513
00514
00515 pwd = getpwuid(geteuid());
00516 if (pwd == NULL) {
00517 return NULL;
00518 }
00519
00520 cli = smb_complete_connection(myname, server, port, pwd->pw_name, "",
00521 workgroup, share, 0);
00522
00523 if (cli) { return cli; }
00524
00525
00526
00527
00528
00529 cli = smb_complete_connection(myname, server, port, "", "",
00530 workgroup, share, 0);
00531
00532
00533
00534
00535 return (cli);
00536 }
00537
00538
00539
00540
00541
00542
00543 static int
00544 smb_print(struct cli_state *cli,
00545 char *title,
00546 FILE *fp)
00547 {
00548 int fnum;
00549 int nbytes,
00550 tbytes;
00551 char buffer[8192],
00552 *ptr;
00553
00554
00555
00556
00557
00558
00559 for (ptr = title; *ptr; ptr ++)
00560 if (!isalnum((int)*ptr) && !isspace((int)*ptr))
00561 *ptr = '_';
00562
00563
00564
00565
00566
00567 if ((fnum = cli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1)
00568 {
00569 fprintf(stderr, "ERROR: %s opening remote spool %s\n",
00570 cli_errstr(cli), title);
00571 return (1);
00572 }
00573
00574
00575
00576
00577
00578 if (fp != stdin)
00579 rewind(fp);
00580
00581 tbytes = 0;
00582
00583 while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
00584 {
00585 if (cli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes)
00586 {
00587 fprintf(stderr, "ERROR: Error writing spool: %s\n", cli_errstr(cli));
00588 break;
00589 }
00590
00591 tbytes += nbytes;
00592 }
00593
00594 if (!cli_close(cli, fnum))
00595 {
00596 fprintf(stderr, "ERROR: %s closing remote spool %s\n",
00597 cli_errstr(cli), title);
00598 return (1);
00599 }
00600 else
00601 return (0);
00602 }
00603
00604 static char *uri_unescape_alloc(const char *uritok)
00605 {
00606 char *ret;
00607
00608 ret = (char *)SMB_STRDUP(uritok);
00609 if (!ret) return NULL;
00610
00611 rfc1738_unescape(ret);
00612 return ret;
00613 }