Beispiel #1
0
int
main(int argc, char *argv[])
{
	int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0;
	char *options, *value;
	extern char *optarg;
	extern int optind;
	int c, d;
	struct rlimit rl;
	int mode = RPC_SVC_MT_AUTO;
	int maxrecsz = RPC_MAXDATASIZE;

	void detachfromtty(void);
	int setmodulus();
	int pk_nodefaultkeys();
	int svc_create_local_service();

	char domainname[MAXNETNAMELEN + 1];

	/*
	 * Set our allowed number of file descriptors to the max
	 * of what the system will allow, limited by FD_SETSIZE.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		rlim_t limit;

		if ((limit = rl.rlim_max) > FD_SETSIZE)
			limit = FD_SETSIZE;
		rl.rlim_cur = limit;
		(void) setrlimit(RLIMIT_NOFILE, &rl);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	__key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc;
	__key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc;
	__key_gendes_LOCAL = &__key_gen_1_svc;

	/*
	 * Pre-option initialisation
	 */
	(void) umask(066);	/* paranoia */
	if (geteuid() != 0) {
		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
		exit(1);
	}
	setmodulus(HEXMODULUS);
	openlog("keyserv", LOG_PID, LOG_DAEMON);

	/*
	 * keyserv will not work with a null domainname.
	 */
	if (getdomainname(domainname, MAXNETNAMELEN+1) ||
	    (domainname[0] == '\0')) {
		syslog(LOG_ERR, "could not get a valid domainname.\n");
		exit(SMF_EXIT_ERR_CONFIG);
	}

	/*
	 * Initialise security mechanisms
	 */
	cache_size = NULL;
	cache_options = NULL;
	if (init_mechs() == -1) {
		disk_caching = 0;
	}

	defaults();

	while ((c = getopt(argc, argv, "ndDet:cs:")) != -1)
		switch (c) {
		case 'n':
			nflag++;
			break;
		case 'd':
			dflag++;
			use_nobody_keys = FALSE;
			break;
		case 'e':
			eflag++;
			use_nobody_keys = TRUE;
			break;
		case 'D':
			debugging = 1;
			break;
		case 't':
			nthreads = atoi(optarg);
			break;
		case 'c':
			disk_caching = 0;
			break;
		case 's':
			if (!disk_caching) {
				fprintf(stderr, "missing configuration file");
				fprintf(stderr, " or -c option specified\n");
				usage();
			}
			sflag++;
			/*
			 * Which version of [-s] do we have...?
			 */
			if (strchr((const char *) optarg, '=') == NULL) {
				/*
				 * -s <size>
				 */
				if (s1flag) {
					fprintf(stderr, "duplicate"
					    " [-s <size>]\n");
					usage();
				}
				s1flag++;
				default_cache = get_cache_size(optarg);
				break;
			}
			/*
			 * -s <mechtype>=<size>[,...]
			 */
			s2flag++;
			options = optarg;
			while (*options != '\0') {
				d = getsubopt(&options, cache_options, &value);
				if (d == -1) {
					/* Ignore unknown mechtype */
					continue;
				}
				if (value == NULL) {
					fprintf(stderr,
					    "missing cache size for "
					    "mechtype %s\n", cache_options[d]);
					usage();
				}
				cache_size[d] = get_cache_size(value);
			}
			break;
		default:
			usage();
			break;
		}


	if (dflag && eflag) {
		(void) fprintf(stderr, "specify only one of -d and -e\n");
		usage();
	}

	if (use_nobody_keys == FALSE) {
		pk_nodefaultkeys();
	}

	if (optind != argc) {
		usage();
	}

	if (!disk_caching && sflag) {
		fprintf(stderr, "missing configuration file");
		fprintf(stderr, " or -c option specified\n");
		usage();
	}

	if (debugging) {
		if (disk_caching) {
			char **cpp = cache_options;
			int *ip = cache_size;
			(void) fprintf(stderr, "default disk cache size: ");
			if (default_cache < 0) {
				(void) fprintf(stderr, "%d entries\n",
				    abs(default_cache));
			} else {
				(void) fprintf(stderr, "%dMB\n", default_cache);
			}

			(void) fprintf(stderr, "supported mechanisms:\n");
			(void) fprintf(stderr, "\talias\t\tdisk cache size\n");
			(void) fprintf(stderr, "\t=====\t\t===============\n");
			while (*cpp != NULL) {
				(void) fprintf(stderr, "\t%s\t\t", *cpp++);
				if (*ip < 0) {
					(void) fprintf(stderr, "%d entries\n",
					    abs(*ip));
				} else {
					(void) fprintf(stderr, "%dMB\n", *ip);
				}
				ip++;
			}
		} else {
			(void) fprintf(stderr,
			    "common key disk caching disabled\n");
		}
	}
	/*
	 * Post-option initialisation
	 */
	if (disk_caching) {
		int i;
		for (i = 0; mechs[i]; i++) {
			if ((AUTH_DES_COMPAT_CHK(mechs[i])) ||
			    (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0))
				continue;
			create_cache_file(mechs[i]->keylen, mechs[i]->algtype,
			    cache_size[i] ? cache_size[i] : default_cache);
		}
	}
	getrootkey(&masterkey, nflag);

	/*
	 * Set MT mode
	 */
	if (nthreads > 0) {
		(void) rpc_control(RPC_SVC_MTMODE_SET, &mode);
		(void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads);
	}

	/*
	 * Enable non-blocking mode and maximum record size checks for
	 * connection oriented transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
		syslog(LOG_INFO, "unable to set max RPC record size");
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	if (!debugging) {
		detachfromtty();
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	svc_run();
	abort();
	/* NOTREACHED */
	return (0);
}
Beispiel #2
0
static int open_cache_file(char const *conf_file,
			   char const *cache_file,
			   char const *cache_prog)
{
	bool			regen_cache;
	int			conf_fd = -1;
	int			cache_fd = -1;
	int			rc;

	conf_fd = open(conf_file, O_RDONLY);
	if (conf_fd < 0) {
		perror("open(<conf>)");
		rc = -EX_UNAVAILABLE;
		goto err;
	}
	if (flock(conf_fd, LOCK_SH) < 0) {
		perror("flock(<conf>, LOCK_SH)");
		rc = -EX_IOERR;
		goto err;
	}

again:
	regen_cache = false;
	errno = 0;
	cache_fd = open(cache_file, O_RDONLY);
	if (cache_fd < 0 && errno == ENOENT)
		regen_cache = true;
	else if (cache_fd < 0) {
		perror("open(<cache_file>, O_RDONLY)");
		rc = -EX_UNAVAILABLE;
		goto err;
	} else {
		struct stat	st_conf;
		struct stat	st_cache;

		if (flock(cache_fd, LOCK_SH) < 0) {
			perror("flock(<cache>, LOCK_SH)");
			rc = -EX_IOERR;
			goto err;
		}

		if (fstat(conf_fd, &st_conf) < 0 ||
		    fstat(cache_fd, &st_cache) < 0) {
			perror("fstat()");
			rc = -EX_IOERR;
			goto err;
		}

		if (st_conf.st_mtime > st_cache.st_mtime ||
		    st_cache.st_size == 0) {
			if (flock(cache_fd, LOCK_EX) < 0) {
				perror("flock(<cache>, LOCK_EX)");
				rc = -EX_IOERR;
				goto err;
			}

			regen_cache = true;
		}
	}

	if (regen_cache) {
		rc = create_cache_file(conf_fd, cache_file,
				       cache_prog, cache_fd < 0);

		if (rc < 0)
			goto err;

		if (cache_fd < 0)
			goto again;

		if (flock(cache_fd, LOCK_SH) < 0) {
			perror("flock(<cache>, LOCK_SH)");
			rc = -EX_IOERR;
			goto err;
		}
	}

	close(conf_fd);
	lseek(cache_fd, 0, SEEK_SET);

	return cache_fd;

err:
	if (cache_fd >= 0)
		close(cache_fd);

	if (conf_fd >= 0)
		close(conf_fd);

	return rc;
}