2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 1983 Regents of the University of California.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by the University of California, Berkeley. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
25 #include <priv_utils.h>
30 * Remote distribution program.
33 char *distfile
= NULL
;
34 char Tmpfile
[] = "/tmp/rdistXXXXXX";
35 char *tmpname
= &Tmpfile
[5];
37 int debug
; /* debugging flag */
38 int nflag
; /* NOP flag, just print commands without executing */
39 int qflag
; /* Quiet. Don't print messages */
40 int options
; /* global options */
41 int iamremote
; /* act as remote server for transfering files */
43 FILE *fin
= NULL
; /* input file pointer */
44 int rem
= -1; /* file descriptor to remote source/sink process */
45 char host
[32]; /* host name */
46 int nerrs
; /* number of errors while sending/receiving */
47 char user
[10]; /* user's name */
48 char homedir
[128]; /* user's home directory */
49 char buf
[RDIST_BUFSIZ
]; /* general purpose buffer */
51 struct passwd
*pw
; /* pointer to static area used by getpwent */
52 struct group
*gr
; /* pointer to static area used by getgrent */
54 char des_inbuf
[2 * RDIST_BUFSIZ
]; /* needs to be > largest read size */
55 char des_outbuf
[2 * RDIST_BUFSIZ
]; /* needs to be > largest write size */
56 krb5_data desinbuf
, desoutbuf
;
57 krb5_encrypt_block eblock
; /* eblock for encrypt/decrypt */
58 krb5_context bsd_context
= NULL
;
59 krb5_auth_context auth_context
;
61 char *krb_cache
= NULL
;
63 krb5_error_code status
;
64 enum kcmd_proto kcmd_proto
= KCMD_NEW_PROTOCOL
;
66 int encrypt_flag
= 0; /* Flag set when encryption is used */
67 int krb5auth_flag
= 0; /* Flag set, when KERBEROS is enabled */
68 static profile_options_boolean autologin_option
[] = {
69 { "autologin", &krb5auth_flag
, 0 },
72 static int no_krb5auth_flag
= 0;
77 char *krb_realm
= NULL
;
79 /* Flag set, if -PN / -PO is specified */
80 static boolean_t rcmdoption_done
= B_FALSE
;
82 static int encrypt_done
= 0; /* Flag set, if -x is specified */
83 profile_options_boolean option
[] = {
84 { "encrypt", &encrypt_flag
, 0 },
88 static char *rcmdproto
= NULL
;
89 profile_option_strings rcmdversion
[] = {
90 { "rcmd_protocol", &rcmdproto
, 0 },
94 char *realmdef
[] = { "realms", NULL
, "rdist", NULL
};
95 char *appdef
[] = { "appdefaults", "rdist", NULL
};
97 static void usage(void);
98 static char *prtype(int t
);
99 static void prsubcmd(struct subcmd
*s
);
100 static void docmdargs(int nargs
, char *args
[]);
111 char *dhosts
[NHOSTS
], **hp
= dhosts
;
113 (void) setlocale(LC_ALL
, "");
115 pw
= getpwuid(getuid());
117 (void) fprintf(stderr
, gettext("%s: Who are you?\n"), argv
[0]);
120 strncpy(user
, pw
->pw_name
, sizeof (user
));
121 user
[sizeof (user
) - 1] = '\0';
122 strncpy(homedir
, pw
->pw_dir
, sizeof (homedir
));
123 homedir
[sizeof (homedir
) - 1] = '\0';
124 gethostname(host
, sizeof (host
));
127 if ((arg
= *++argv
)[0] != '-')
129 if ((strcmp(arg
, "-Server") == 0))
131 else while (*++arg
) {
132 if (strncmp(*argv
, "-PO", 3) == 0) {
133 if (rcmdoption_done
== B_TRUE
) {
134 (void) fprintf(stderr
, gettext("rdist: "
136 "and -PO allowed.\n"));
139 kcmd_proto
= KCMD_OLD_PROTOCOL
;
141 rcmdoption_done
= B_TRUE
;
144 if (strncmp(*argv
, "-PN", 3) == 0) {
145 if (rcmdoption_done
== B_TRUE
) {
146 (void) fprintf(stderr
, gettext("rdist: "
148 "and -PO allowed.\n"));
151 kcmd_proto
= KCMD_NEW_PROTOCOL
;
153 rcmdoption_done
= B_TRUE
;
162 debug_port
= htons(atoi(*++argv
));
167 (void) fprintf(stderr
, gettext("rdist: "
168 "-k flag must be followed with "
169 " a realm name.\n"));
172 if ((krb_realm
= strdup(*++argv
)) == NULL
) {
173 (void) fprintf(stderr
, gettext("rdist: "
174 "Cannot malloc.\n"));
198 if (distfile
[0] == '-' && distfile
[1] == '\0')
205 if (hp
>= &dhosts
[NHOSTS
-2]) {
206 (void) fprintf(stderr
, gettext("rdist:"
207 " too many destination"
229 if (options
& VERIFY
) {
230 printf("rdist: -n overrides -v\n");
250 printf("rdist: -n overrides -v\n");
282 * if the user disables krb5 on the cmdline (-K), then skip
285 * if the user does not disable krb5 or enable krb5 on the
286 * cmdline, check krb5.conf to see if it should be enabled.
289 if (no_krb5auth_flag
) {
292 } else if (!krb5auth_flag
) {
293 /* is autologin set in krb5.conf? */
294 status
= krb5_init_context(&bsd_context
);
295 /* don't sweat failure here */
298 * note that the call to profile_get_options_boolean
299 * with autologin_option can affect value of
302 (void) profile_get_options_boolean(bsd_context
->profile
,
308 if (krb5auth_flag
> 0) {
310 status
= krb5_init_context(&bsd_context
);
312 com_err("rdist", status
,
313 gettext("while initializing krb5"));
318 /* Set up des buffers */
319 desinbuf
.data
= des_inbuf
;
320 desoutbuf
.data
= des_outbuf
;
321 desinbuf
.length
= sizeof (des_inbuf
);
322 desoutbuf
.length
= sizeof (des_outbuf
);
325 * Get our local realm to look up local realm options.
327 status
= krb5_get_default_realm(bsd_context
, &realmdef
[1]);
329 com_err("rdist", status
,
330 gettext("while getting default realm"));
334 * See if encryption should be done for this realm
336 profile_get_options_boolean(bsd_context
->profile
, realmdef
,
339 * Check the appdefaults section
341 profile_get_options_boolean(bsd_context
->profile
, appdef
,
343 profile_get_options_string(bsd_context
->profile
, appdef
,
346 if ((encrypt_done
> 0) || (encrypt_flag
> 0)) {
347 if (krb5_privacy_allowed() == TRUE
) {
350 (void) fprintf(stderr
, gettext("rdist: "
351 "Encryption not supported.\n"));
356 if ((rcmdoption_done
== B_FALSE
) && (rcmdproto
!= NULL
)) {
357 if (strncmp(rcmdproto
, "rcmdv2", 6) == 0) {
358 kcmd_proto
= KCMD_NEW_PROTOCOL
;
359 } else if (strncmp(rcmdproto
, "rcmdv1", 6) == 0) {
360 kcmd_proto
= KCMD_OLD_PROTOCOL
;
362 (void) fprintf(stderr
, gettext("Unrecognized "
363 "KCMD protocol (%s)"), rcmdproto
);
370 setreuid(getuid(), getuid());
374 if (__init_suid_priv(0, PRIV_NET_PRIVADDR
, NULL
) == -1) {
375 (void) fprintf(stderr
,
376 "rdist needs to run with sufficient privilege\n");
381 docmdargs(argc
, argv
);
384 if (distfile
== NULL
) {
385 if ((fin
= fopen("distfile", "r")) == NULL
)
386 fin
= fopen("Distfile", "r");
388 fin
= fopen(distfile
, "r");
390 perror(distfile
? distfile
: "distfile");
396 docmds(dhosts
, argc
, argv
);
405 printf(gettext("Usage: rdist [-nqbhirvwyDax] [-PN / -PO] "
409 "[-k realm] [-f distfile] [-d var=value] [-m host] [file ...]\n"));
410 printf(gettext("or: rdist [-nqbhirvwyDax] [-PN / -PO] [-p port] "
411 "[-k realm] -c source [...] machine[:dest]\n"));
416 * rcp like interface for distributing files.
419 docmdargs(nargs
, args
)
423 register struct namelist
*nl
, *prev
;
425 struct namelist
*files
, *hosts
;
428 static struct namelist tnl
= { NULL
, NULL
};
435 for (i
= 0; i
< nargs
- 1; i
++) {
436 nl
= makenl(args
[i
]);
446 if ((dest
= index(cp
, ':')) != NULL
)
449 hosts
= expand(&tnl
, E_ALL
);
453 if (dest
== NULL
|| *dest
== '\0')
456 cmds
= makesubcmd(INSTALL
);
457 cmds
->sc_options
= options
;
458 cmds
->sc_name
= dest
;
462 printf("docmdargs()\nfiles = ");
467 insert(NULL
, files
, hosts
, cmds
);
468 docmds(NULL
, 0, NULL
);
472 * Print a list of NAME blocks (mostly for debugging).
476 register struct namelist
*nl
;
480 printf("%s ", nl
->n_name
);
490 extern char *prtype();
493 printf("c_type %s, c_name %s, c_label %s, c_files ",
494 prtype(c
->c_type
), c
->c_name
,
495 c
->c_label
? c
->c_label
: "NULL");
506 extern char *prtype();
507 extern char *proptions();
510 printf("sc_type %s, sc_options %d%s, sc_name %s, sc_args ",
512 s
->sc_options
, proptions(s
->sc_options
),
513 s
->sc_name
? s
->sc_name
: "NULL");
562 return (printb((unsigned short) o
, OBITS
));
568 register unsigned short v
;
570 register int i
, any
= 0;
578 while ((i
= *bits
++) != 0) {
579 if (v
& (1 << (i
-1))) {
583 for (; (c
= *bits
) > 32; bits
++)
586 for (; *bits
> 32; bits
++)