Пример #1
0
void
ka_StringToKey(char *str, char *cell,	/* cell for password */
	       struct ktc_encryptionKey *key)
{
    char realm[MAXKTCREALMLEN];
    afs_int32 code;

    LOCK_GLOBAL_MUTEX;
    code = ka_CellToRealm(cell, realm, 0 /*local */ );
    if (code)			/* just take his word for it */
	strncpy(realm, cell, sizeof(realm));
    else			/* for backward compatibility */
	lcstring(realm, realm, sizeof(realm));
    if (strlen(str) > 8)
	StringToKey(str, realm, key);
    else
	Andrew_StringToKey(str, realm, key);
    UNLOCK_GLOBAL_MUTEX;
}
Пример #2
0
int
unlog_NormalizeCellNames(char **list, int size)
{
    char *newCellName;
    unsigned index;
    struct afsconf_dir *conf;
    int code;
    struct afsconf_cell cellinfo;

    if (!(conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
	fprintf(stderr, "Cannot get cell configuration info!\n");
	exit(1);
    }

    for (index = 0; index < size; index++, list++) {
	newCellName = malloc(MAXKTCREALMLEN);
	if (!newCellName) {
	    perror("unlog_NormalizeCellNames --- malloc failed");
	    exit(1);
	}

	lcstring(newCellName, *list, MAXKTCREALMLEN);
	code = afsconf_GetCellInfo(conf, newCellName, 0, &cellinfo);
	if (code) {
	    if (code == AFSCONF_NOTFOUND) {
		fprintf(stderr, "Unrecognized cell name %s\n", newCellName);
	    } else {
		fprintf(stderr,
			"unlog_NormalizeCellNames - afsconf_GetCellInfo");
		fprintf(stderr, " failed, code = %d\n", code);
	    }
	    exit(1);
	}


	strcpy(newCellName, cellinfo.name);

	*list = newCellName;
    }
    afsconf_Close(conf);
    return 0;
}
Пример #3
0
int
main(int argc, char **argv)
{
    char *p, *ename;
    char const *const *cpp;
    int got_language = 0;
    char *got_include = 0;
    char *got_prefix = ".";
    char lcname[6];

#ifdef	AFS_AIX32_ENV
    /*
     * The following signal action for AIX is necessary so that in case of a
     * crash (i.e. core is generated) we can include the user's data section
     * in the core dump. Unfortunately, by default, only a partial core is
     * generated which, in many cases, isn't too useful.
     */
    struct sigaction nsa;

    sigemptyset(&nsa.sa_mask);
    nsa.sa_handler = SIG_DFL;
    nsa.sa_flags = SA_FULLDUMP;
    sigaction(SIGSEGV, &nsa, NULL);
#endif
    /* argument parsing */
    debug = 0;
    filename = 0;
    whoami = argv[0];
    p = strrchr(whoami, '/');
    if (p)
	whoami = p + 1;
    while (argv++, --argc) {
	char *arg = *argv;
	if (arg[0] != '-') {
	    if (filename)
		dup_err("filenames", filename, arg);
	    filename = arg;
	} else {
	    arg++;
	    if (check_arg(debug_args, arg))
		debug++;
	    else if (check_arg(lang_args, arg)) {
		got_language++;
		arg = *++argv, argc--;
		if (!arg)
		    usage();
		if (language)
		    dup_err("languanges", language_names[(int)language], arg);

#define check_lang(x,v) if (!strcasecmp(arg,x)) language = v
		check_lang("c", lang_C);
		check_lang("ansi_c", lang_C);
		check_lang("ansi-c", lang_C);
		check_lang("krc", lang_KRC);
		check_lang("kr_c", lang_KRC);
		check_lang("kr-c", lang_KRC);
		check_lang("k&r-c", lang_KRC);
		check_lang("k&r_c", lang_KRC);
		check_lang("c++", lang_CPP);
		check_lang("cplusplus", lang_CPP);
		check_lang("c-plus-plus", lang_CPP);
#undef check_lang

		if (!language) {
		    fprintf(stderr, "%s: unknown language name `%s'\n",
			    whoami, arg);
		    fprintf(stderr, "\tpick one of: C K&R-C\n");
		    exit(1);
		}
	    } else if (strcmp(arg, "h") == 0) {
		arg = *++argv, argc--;
		if (!arg)
		    usage();
		got_include = arg;
	    } else if (strcmp(arg, "p") == 0) {
		arg = *++argv, argc--;
		if (!arg)
		    usage();
		got_prefix = arg;
	    } else if (strcmp(arg, "v") == 0) {
		arg = *++argv, argc--;
		version = atoi(arg);
		if (version != 1 && version != 2) {
		    fprintf(stderr, "%s: unknown control argument -`%s'\n",
			    whoami, arg);
		    usage();
		    exit(1);
		}
		if (version == 2)
		    use_msf = 1;
	    } else {
		fprintf(stderr, "%s: unknown control argument -`%s'\n",
			whoami, arg);
		usage();
	    }
	}
    }
    if (!filename)
	usage();
    if (!got_language)
	language = lang_C;
    else if (language == lang_CPP) {
	fprintf(stderr, "%s: Sorry, C++ support is not yet finished.\n",
		whoami);
	exit(1);
    }


    p = strrchr(filename, '/');
    if (p == (char *)NULL)
	p = filename;
    else
	p++;
    ename = xmalloc(strlen(p) + 5);
    strcpy(ename, p);

    /* Now, flush .et suffix if it exists.   */
    p = strrchr(ename, '.');
    if (p != NULL) {
	if (strcmp(p, ".et") == 0)
	    *p = 0;
    }

    if (use_msf) {
	sprintf(msf_file, "%s.msf", ename);
    } else {
	sprintf(c_file, "%s.c", ename);
    }
    if (got_include) {
	sprintf(h_file, "%s.h", got_include);
    } else {
	sprintf(h_file, "%s.h", ename);
    }
    p = strrchr(filename, '.');
    if (p == NULL) {
	p = xmalloc(strlen(filename) + 4);
	sprintf(p, "%s.et", filename);
	filename = p;
    }

    sprintf(et_file, "%s/%s", got_prefix, filename);

    yyin = fopen(et_file, "r");
    if (!yyin) {
	perror(et_file);
	exit(1);
    }

    /* on NT, yyout is not initialized to stdout */
    if (!yyout) {
	yyout = stdout;
    }

    hfile = fopen(h_file, "w");
    if (hfile == (FILE *) NULL) {
	perror(h_file);
	exit(1);
    }
    fprintf(hfile, warning, h_file);
    if (got_include) {
	char buffer[BUFSIZ];
	char prolog_h_file[MAXPATHLEN];
	FILE *prolog_hfile;
	int count, written;

	strcpy(prolog_h_file, got_prefix);
	strcat(prolog_h_file, "/");
	strcat(prolog_h_file, got_include);
	strcat(prolog_h_file, ".p.h");
	prolog_hfile = fopen(prolog_h_file, "r");
	if (prolog_hfile) {
	    fprintf(stderr, "Including %s at beginning of %s file.\n",
		    prolog_h_file, h_file);
	    fprintf(hfile, "/* Including %s at beginning of %s file. */\n\n",
		    prolog_h_file, h_file);
	    do {
		count =
		    fread(buffer, sizeof(char), sizeof(buffer), prolog_hfile);
		if (count == EOF) {
		    perror(prolog_h_file);
		    exit(1);
		}
		written = fwrite(buffer, sizeof(char), count, hfile);
		if (count != written) {
		    perror(prolog_h_file);
		    exit(1);
		}
	    } while (count > 0);
	    fprintf(hfile, "\n/* End of prolog file %s. */\n\n",
		    prolog_h_file);
	}
    }

    if (use_msf) {
	msfile = fopen(msf_file, "w");
	if (msfile == (FILE *) NULL) {
	    perror(msf_file);
	    exit(1);
	}
	fprintf(msfile, msf_warning, msf_file);
    } else {
	cfile = fopen(c_file, "w");
	if (cfile == (FILE *) NULL) {
	    perror(c_file);
	    exit(1);
	}
	fprintf(cfile, warning, c_file);

	/* prologue */
	if (language == lang_C)
	    cpp = c_src_prolog;
	else if (language == lang_KRC)
	    cpp = krc_src_prolog;
	else
	    abort();
	while (*cpp)
	    fputs(*cpp++, cfile);
    }

    /* parse it */
    yyparse();
    fclose(yyin);		/* bye bye input file */

    if (!use_msf) {
	fputs("    0\n};\n\n", cfile);
	fprintf(cfile,
		"static const struct error_table et = { text, %ldL, %d };\n\n",
		(long int)table_number, current);
	fputs("static struct et_list etlink = { 0, &et};\n\n", cfile);
	fprintf(cfile, "void initialize_%s_error_table(void) {\n",
		table_name);
	fputs("    afs_add_to_error_table(&etlink);\n", cfile);
	fputs("}\n", cfile);
	fclose(cfile);


	fprintf(hfile, "extern void initialize_%s_error_table(void);\n",
		table_name);
    } else {
	fprintf(hfile, "#define initialize_%s_error_table(void)\n",
		table_name);
    }

    fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", table_name,
	    (long int)table_number);
    /* compatibility... */
    fprintf(hfile, "\n/* for compatibility with older versions... */\n");
    fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
	    table_name, table_name);
    fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
	    table_name);
    fprintf(hfile, "\n/* for compatibility with other users... */\n");
    lcstring(lcname, table_name, sizeof(lcname));
    fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", lcname,
	    (long int)table_number);
    fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
	    lcname, table_name);
    fprintf(hfile,
	    "#define initialize_%s_error_table initialize_%s_error_table\n",
	    lcname, table_name);
    fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", lcname,
	    lcname);
    fclose(hfile);		/* bye bye include file */
    if (use_msf)
	fclose(msfile);
    return 0;
}
Пример #4
0
int
afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
		    struct afsconf_cell *acellInfo)
{
    struct afsconf_entry *tce;
    struct afsconf_aliasentry *tcae;
    struct afsconf_entry *bestce;
    afs_int32 i;
    int tservice;
    char *tcell;
    int cnLen;
    int ambig;
    char tbuffer[64];

    LOCK_GLOBAL_MUTEX;
    if (adir)
	_afsconf_Check(adir);
    if (acellName) {
	tcell = acellName;
	cnLen = (int)(strlen(tcell) + 1);
	lcstring(tcell, tcell, cnLen);
	afsconf_SawCell = 1;	/* will ignore the AFSCELL switch on future */
	/* call to afsconf_GetLocalCell: like klog  */
    } else {
	i = afsconf_GetLocalCell(adir, tbuffer, sizeof(tbuffer));
	if (i) {
	    UNLOCK_GLOBAL_MUTEX;
	    return i;
	}
	tcell = tbuffer;
    }
    cnLen = strlen(tcell);
    bestce = (struct afsconf_entry *)0;
    ambig = 0;
    if (!adir) {
	UNLOCK_GLOBAL_MUTEX;
	return 0;
    }

    /* Look through the list of aliases */
    for (tcae = adir->alias_entries; tcae; tcae = tcae->next) {
	if (strcasecmp(tcae->aliasInfo.aliasName, tcell) == 0) {
	    tcell = tcae->aliasInfo.realName;
	    break;
	}
    }

    for (tce = adir->entries; tce; tce = tce->next) {
	if (strcasecmp(tce->cellInfo.name, tcell) == 0) {
	    /* found our cell */
	    bestce = tce;
	    ambig = 0;
	    break;
	}
	if (strlen(tce->cellInfo.name) < cnLen)
	    continue;		/* clearly wrong */
	if (strncasecmp(tce->cellInfo.name, tcell, cnLen) == 0) {
	    if (bestce)
		ambig = 1;	/* ambiguous unless we get exact match */
	    bestce = tce;
	}
    }
    if (!ambig && bestce && bestce->cellInfo.numServers) {
	*acellInfo = bestce->cellInfo;	/* structure assignment */
	if (aservice) {
	    tservice = afsconf_FindService(aservice);
	    if (tservice < 0) {
		UNLOCK_GLOBAL_MUTEX;
		return AFSCONF_NOTFOUND;	/* service not found */
	    }
	    for (i = 0; i < acellInfo->numServers; i++) {
		acellInfo->hostAddr[i].sin_port = tservice;
	    }
	}
	acellInfo->timeout = 0;

        /*
         * Until we figure out how to separate out ubik server
         * queries from other server queries, only perform gethostbyname()
         * lookup on the specified hostnames for the client CellServDB files.
         */
        if (_afsconf_IsClientConfigDirectory(adir->name) &&
            !(acellInfo->flags & AFSCONF_CELL_FLAG_DNS_QUERIED)) {
            int j;
            short numServers=0;		                        /*Num active servers for the cell */
            struct sockaddr_in hostAddr[MAXHOSTSPERCELL];	/*IP addresses for cell's servers */
            char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS];	/*Names for cell's servers */
            char clone[MAXHOSTSPERCELL];			/*Indicates which ones are clones. */

            memset(&hostAddr, 0, sizeof(hostAddr));
            memset(&hostName, 0, sizeof(hostName));
            memset(&clone, 0, sizeof(clone));

            for ( j=0; j<acellInfo->numServers && numServers < MAXHOSTSPERCELL; j++ ) {
                struct hostent *he = gethostbyname(acellInfo->hostName[j]);
                int foundAddr = 0;

                if (he && he->h_addrtype == AF_INET) {
                    int i;
                    /* obtain all the valid address from the list */
                    for (i=0 ; he->h_addr_list[i] && numServers < MAXHOSTSPERCELL; i++) {
                        /* check to see if this is a new address; if so insert it into the list */
                        int k, dup;
			afs_uint32 addr;
			memcpy(&addr, he->h_addr_list[i], sizeof(addr));
                        for (k=0, dup=0; !dup && k < numServers; k++) {
                            if (hostAddr[k].sin_addr.s_addr == addr) {
                                dup = 1;
			    }
                        }
                        if (dup)
                            continue;

                        hostAddr[numServers].sin_family = AF_INET;
                        hostAddr[numServers].sin_port = acellInfo->hostAddr[0].sin_port;
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
                        hostAddr[numServers].sin_len = sizeof(struct sockaddr_in);
#endif
                        memcpy(&hostAddr[numServers].sin_addr.s_addr, he->h_addr_list[i], sizeof(afs_uint32));
                        strcpy(hostName[numServers], acellInfo->hostName[j]);
                        clone[numServers] = acellInfo->clone[j];
                        foundAddr = 1;
                        numServers++;
                    }
                }
                if (!foundAddr) {
                    hostAddr[numServers] = acellInfo->hostAddr[j];
                    strcpy(hostName[numServers], acellInfo->hostName[j]);
                    clone[numServers] = acellInfo->clone[j];
                    numServers++;
                }
            }

            for (i=0; i<numServers; i++) {
                acellInfo->hostAddr[i] = hostAddr[i];
                strcpy(acellInfo->hostName[i], hostName[i]);
                acellInfo->clone[i] = clone[i];
            }
            acellInfo->numServers = numServers;
            acellInfo->flags |= AFSCONF_CELL_FLAG_DNS_QUERIED;
        }
	UNLOCK_GLOBAL_MUTEX;
	return 0;
    } else {
	UNLOCK_GLOBAL_MUTEX;
	return afsconf_GetAfsdbInfo(tcell, aservice, acellInfo);
    }
}
Пример #5
0
int
main(int argc, char *argv[])
{
    afs_int32 code;
    char *whoami = argv[0];
    afs_uint32 serverList[MAXSERVERS];
    struct afsconf_cell cellinfo;
    char *cell;
    const char *cellservdb, *dbpath, *lclpath;
    int a;
    char arg[32];
    char default_lclpath[AFSDIR_PATH_MAX];
    int servers;
    int initFlags;
    int level;			/* security level for Ubik */
    afs_int32 i;
    char clones[MAXHOSTSPERCELL];
    afs_uint32 host = ntohl(INADDR_ANY);
    char *auditFileName = NULL;

    struct rx_service *tservice;
    struct rx_securityClass *sca[1];
    struct rx_securityClass *scm[3];

    extern int rx_stackSize;

#ifdef	AFS_AIX32_ENV
    /*
     * The following signal action for AIX is necessary so that in case of a
     * crash (i.e. core is generated) we can include the user's data section
     * in the core dump. Unfortunately, by default, only a partial core is
     * generated which, in many cases, isn't too useful.
     */
    struct sigaction nsa;

    sigemptyset(&nsa.sa_mask);
    nsa.sa_handler = SIG_DFL;
    nsa.sa_flags = SA_FULLDUMP;
    sigaction(SIGABRT, &nsa, NULL);
    sigaction(SIGSEGV, &nsa, NULL);
#endif
    osi_audit_init();

    if (argc == 0) {
      usage:
	printf("Usage: kaserver [-noAuth] [-database <dbpath>] "
	       "[-auditlog <log path>] [-audit-interface <file|sysvmq>] "
	       "[-rxbind] [-localfiles <lclpath>] [-minhours <n>] "
	       "[-servers <serverlist>] [-crossrealm] "
	       /*" [-enable_peer_stats] [-enable_process_stats] " */
	       "[-help]\n");
	exit(1);
    }
#ifdef AFS_NT40_ENV
    /* initialize winsock */
    if (afs_winsockInit() < 0) {
	ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);
	fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami);
	exit(1);
    }
#endif
    /* Initialize dirpaths */
    if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
	ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
	fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
		argv[0]);
	exit(2);
    }

    cellservdb = AFSDIR_SERVER_ETC_DIRPATH;
    dbpath = AFSDIR_SERVER_KADB_FILEPATH;
    strcompose(default_lclpath, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH,
	       "/", AFSDIR_KADB_FILE, NULL);
    lclpath = default_lclpath;

    debugOutput = 0;
    servers = 0;
    initFlags = 0;
    level = rxkad_crypt;
    for (a = 1; a < argc; a++) {
	int arglen = strlen(argv[a]);
	lcstring(arg, argv[a], sizeof(arg));
#define IsArg(a) (strncmp (arg,a, arglen) == 0)

	if (strcmp(arg, "-database") == 0) {
	    dbpath = argv[++a];
	    if (strcmp(lclpath, default_lclpath) == 0)
		lclpath = dbpath;
	}
	else if (strncmp(arg, "-auditlog", arglen) == 0) {
	    auditFileName = argv[++a];

	} else if (strncmp(arg, "-audit-interface", arglen) == 0) {
	    char *interface = argv[++a];

	    if (osi_audit_interface(interface)) {
		printf("Invalid audit interface '%s'\n", interface);
		exit(1);
	    }

	} else if (strcmp(arg, "-localfiles") == 0)
	    lclpath = argv[++a];
	else if (strcmp(arg, "-servers") == 0)
	    debugOutput++, servers = 1;
	else if (strcmp(arg, "-noauth") == 0)
	    debugOutput++, initFlags |= 1;
	else if (strcmp(arg, "-fastkeys") == 0)
	    debugOutput++, initFlags |= 4;
	else if (strcmp(arg, "-dbfixup") == 0)
	    debugOutput++, initFlags |= 8;
	else if (strcmp(arg, "-cellservdb") == 0) {
	    cellservdb = argv[++a];
	    initFlags |= 2;
	    debugOutput++;
	}

	else if (IsArg("-crypt"))
	    level = rxkad_crypt;
	else if (IsArg("-safe"))
	    level = rxkad_crypt;
	else if (IsArg("-clear"))
	    level = rxkad_clear;
	else if (IsArg("-sorry"))
	    level = rxkad_clear;
	else if (IsArg("-debug"))
	    verbose_track = 0;
	else if (IsArg("-crossrealm"))
	    krb4_cross = 1;
	else if (IsArg("-rxbind"))
	    rxBind = 1;
	else if (IsArg("-minhours")) {
	    MinHours = atoi(argv[++a]);
	} else if (IsArg("-enable_peer_stats")) {
	    rx_enablePeerRPCStats();
	} else if (IsArg("-enable_process_stats")) {
	    rx_enableProcessRPCStats();
	} else if (*arg == '-') {
	    /* hack to support help flag */
	    goto usage;
	}
    }

    if (auditFileName) {
	osi_audit_file(auditFileName);
    }

    if ((code = ka_CellConfig(cellservdb)))
	goto abort;
    cell = ka_LocalCell();
    KA_conf = afsconf_Open(cellservdb);
    if (!KA_conf) {
	code = KANOCELLS;
      abort:
	afs_com_err(whoami, code, "Failed getting cell info");
	exit(1);
    }
#ifdef        AUTH_DBM_LOG
    kalog_Init();
#else
    /* NT & HPUX do not have dbm package support. So we can only do some
     * text logging. So open the AuthLog file for logging and redirect
     * stdin and stdout to it
     */
    OpenLog(AFSDIR_SERVER_KALOG_FILEPATH);
    SetupLogSignals();
#endif

    fprintf(stderr, "%s: WARNING: kaserver is deprecated due to its weak security "
	    "properties.  Migrating to a Kerberos 5 KDC is advised.  "
	    "http://www.openafs.org/no-more-des.html\n", whoami);
    ViceLog(0, ("WARNING: kaserver is deprecated due to its weak security properties.  "
	    "Migrating to a Kerberos 5 KDC is advised.  "
	    "http://www.openafs.org/no-more-des.html\n"));

    code =
	afsconf_GetExtendedCellInfo(KA_conf, cell, AFSCONF_KAUTHSERVICE,
				    &cellinfo, clones);
    if (servers) {
	if ((code = ubik_ParseServerList(argc, argv, &myHost, serverList))) {
	    afs_com_err(whoami, code, "Couldn't parse server list");
	    exit(1);
	}
	cellinfo.hostAddr[0].sin_addr.s_addr = myHost;
	for (i = 1; i < MAXSERVERS; i++) {
	    if (!serverList[i])
		break;
	    cellinfo.hostAddr[i].sin_addr.s_addr = serverList[i];
	}
	cellinfo.numServers = i;
    } else {
	code = convert_cell_to_ubik(&cellinfo, &myHost, serverList);
	if (code)
	    goto abort;
	ViceLog(0, ("Using server list from %s cell database.\n", cell));
    }

    /* initialize audit user check */
    osi_audit_set_user_check(KA_conf, KA_IsLocalRealmMatch);

    /* initialize ubik */
    if (level == rxkad_clear)
	ubik_SetClientSecurityProcs(afsconf_ClientAuth, afsconf_UpToDate,
				    KA_conf);
    else if (level == rxkad_crypt)
	ubik_SetClientSecurityProcs(afsconf_ClientAuthSecure,
				    afsconf_UpToDate, KA_conf);
    else {
	ViceLog(0, ("Unsupported security level %d\n", level));
	exit(5);
    }
    ViceLog(0,
	    ("Using level %s for Ubik connections.\n",
	     (level == rxkad_crypt ? "crypt" : "clear")));

    ubik_SetServerSecurityProcs(afsconf_BuildServerSecurityObjects,
				afsconf_CheckAuth,
				KA_conf);

    ubik_nBuffers = 80;

    if (rxBind) {
	afs_int32 ccode;
        if (AFSDIR_SERVER_NETRESTRICT_FILEPATH ||
            AFSDIR_SERVER_NETINFO_FILEPATH) {
            char reason[1024];
            ccode = parseNetFiles(SHostAddrs, NULL, NULL,
                                           ADDRSPERSITE, reason,
                                           AFSDIR_SERVER_NETINFO_FILEPATH,
                                           AFSDIR_SERVER_NETRESTRICT_FILEPATH);
        } else
	{
            ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
        }
        if (ccode == 1) {
            host = SHostAddrs[0];
	    rx_InitHost(host, htons(AFSCONF_KAUTHPORT));
	}
    }

    /* Disable jumbograms */
    rx_SetNoJumbo();

    if (servers)
	code =
	    ubik_ServerInit(myHost, htons(AFSCONF_KAUTHPORT), serverList,
			    dbpath, &KA_dbase);
    else
	code =
	    ubik_ServerInitByInfo(myHost, htons(AFSCONF_KAUTHPORT), &cellinfo,
				  clones, dbpath, &KA_dbase);

    if (code) {
	afs_com_err(whoami, code, "Ubik init failed");
	exit(2);
    }

    sca[RX_SCINDEX_NULL] = rxnull_NewServerSecurityObject();

    tservice =
	rx_NewServiceHost(host, 0, KA_AUTHENTICATION_SERVICE,
			  "AuthenticationService", sca, 1, KAA_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	ViceLog(0, ("Could not create Authentication rx service\n"));
	exit(3);
    }
    rx_SetMinProcs(tservice, 1);
    rx_SetMaxProcs(tservice, 1);


    tservice =
	rx_NewServiceHost(host, 0, KA_TICKET_GRANTING_SERVICE, "TicketGrantingService",
		      sca, 1, KAT_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	ViceLog(0, ("Could not create Ticket Granting rx service\n"));
	exit(3);
    }
    rx_SetMinProcs(tservice, 1);
    rx_SetMaxProcs(tservice, 1);

    scm[RX_SCINDEX_NULL] = sca[RX_SCINDEX_NULL];
    scm[RX_SCINDEX_VAB] = 0;
    scm[RX_SCINDEX_KAD] =
	rxkad_NewServerSecurityObject(rxkad_crypt, 0, kvno_admin_key, 0);
    tservice =
	rx_NewServiceHost(host, 0, KA_MAINTENANCE_SERVICE, "Maintenance", scm, 3,
		      KAM_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	ViceLog(0, ("Could not create Maintenance rx service\n"));
	exit(3);
    }
    rx_SetMinProcs(tservice, 1);
    rx_SetMaxProcs(tservice, 1);
    rx_SetStackSize(tservice, 10000);

    tservice =
	rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats", scm, 3,
		      RXSTATS_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	ViceLog(0, ("Could not create rpc stats rx service\n"));
	exit(3);
    }
    rx_SetMinProcs(tservice, 2);
    rx_SetMaxProcs(tservice, 4);

    initialize_dstats();

    /* allow super users to manage RX statistics */
    rx_SetRxStatUserOk(KA_rxstat_userok);

    rx_StartServer(0);		/* start handling req. of all types */

    if (init_kaprocs(lclpath, initFlags))
	return -1;

    if ((code = init_krb_udp())) {
	ViceLog(0,
		("Failed to initialize UDP interface; code = %d.\n", code));
	ViceLog(0, ("Running without UDP access.\n"));
    }

    ViceLog(0, ("Starting to process AuthServer requests\n"));
    rx_ServerProc(NULL);		/* donate this LWP */
    return 0;
}
Пример #6
0
int
main(int argc, char **argv)
{
    register afs_int32 code;
    afs_uint32 myHost;
    register struct hostent *th;
    char hostname[64];
    struct rx_service *tservice;
    struct rx_securityClass **securityClasses;
    afs_int32 numClasses;
    int kerberosKeys;		/* set if found some keys */
    int lwps = 3;
    char clones[MAXHOSTSPERCELL];
    afs_uint32 host = htonl(INADDR_ANY);

    const char *pr_dbaseName;
    char *whoami = "ptserver";

    int a;
    char arg[100];

    char *auditFileName = NULL;

#ifdef	AFS_AIX32_ENV
    /*
     * The following signal action for AIX is necessary so that in case of a 
     * crash (i.e. core is generated) we can include the user's data section 
     * in the core dump. Unfortunately, by default, only a partial core is
     * generated which, in many cases, isn't too useful.
     */
    struct sigaction nsa;

    sigemptyset(&nsa.sa_mask);
    nsa.sa_handler = SIG_DFL;
    nsa.sa_flags = SA_FULLDUMP;
    sigaction(SIGABRT, &nsa, NULL);
    sigaction(SIGSEGV, &nsa, NULL);
#endif
    osi_audit_init();
    osi_audit(PTS_StartEvent, 0, AUD_END);

    /* Initialize dirpaths */
    if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
	ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
	fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
		argv[0]);
	exit(2);
    }

    pr_dbaseName = AFSDIR_SERVER_PRDB_FILEPATH;

#if defined(SUPERGROUPS)
    /* make sure the structures for database records are the same size */
    if ((sizeof(struct prentry) != ENTRYSIZE)
	|| (sizeof(struct prentryg) != ENTRYSIZE)) {
	fprintf(stderr,
		"The structures for the database records are different"
		" sizes\n" "struct prentry = %" AFS_SIZET_FMT "\n"
                "struct prentryg = %" AFS_SIZET_FMT "\n"
		"ENTRYSIZE = %d\n", sizeof(struct prentry),
		sizeof(struct prentryg), ENTRYSIZE);
	PT_EXIT(1);
    }
#endif

    for (a = 1; a < argc; a++) {
	int alen;
	lcstring(arg, argv[a], sizeof(arg));
	alen = strlen(arg);
	if (strcmp(argv[a], "-d") == 0) {
	    if ((a + 1) >= argc) {
		fprintf(stderr, "missing argument for -d\n"); 
		return -1; 
	    }
	    debuglevel = atoi(argv[++a]);
	    LogLevel = debuglevel;
	} else if ((strncmp(arg, "-database", alen) == 0)
	    || (strncmp(arg, "-db", alen) == 0)) {
	    pr_dbaseName = argv[++a];	/* specify a database */
	} else if (strncmp(arg, "-p", alen) == 0) {
	    lwps = atoi(argv[++a]);
	    if (lwps > 16) {	/* maximum of 16 */
		printf("Warning: '-p %d' is too big; using %d instead\n",
		       lwps, 16);
		lwps = 16;
	    } else if (lwps < 3) {	/* minimum of 3 */
		printf("Warning: '-p %d' is too small; using %d instead\n",
		       lwps, 3);
		lwps = 3;
	    }
#if defined(SUPERGROUPS)
	} else if ((strncmp(arg, "-groupdepth", alen) == 0)
		 || (strncmp(arg, "-depth", alen) == 0)) {
	    depthsg = atoi(argv[++a]);	/* Max search depth for supergroups */
#endif
	} else if (strncmp(arg, "-default_access", alen) == 0) {
	    prp_user_default = prp_access_mask(argv[++a]);
	    prp_group_default = prp_access_mask(argv[++a]);
	}
	else if (strncmp(arg, "-restricted", alen) == 0) {
	    restricted = 1;
	}
	else if (strncmp(arg, "-rxbind", alen) == 0) {
	    rxBind = 1;
	}
	else if (strncmp(arg, "-allow-dotted-principals", alen) == 0) {
	    rxkadDisableDotCheck = 1;
	}
	else if (strncmp(arg, "-enable_peer_stats", alen) == 0) {
	    rx_enablePeerRPCStats();
	} else if (strncmp(arg, "-enable_process_stats", alen) == 0) {
	    rx_enableProcessRPCStats();
	}
#ifndef AFS_NT40_ENV
	else if (strncmp(arg, "-syslog", alen) == 0) {
	    /* set syslog logging flag */
	    serverLogSyslog = 1;
	} else if (strncmp(arg, "-syslog=", MIN(8, alen)) == 0) {
	    serverLogSyslog = 1;
	    serverLogSyslogFacility = atoi(arg + 8);
	}
#endif
	else if (strncmp(arg, "-auditlog", alen) == 0) {
	    auditFileName = argv[++a];

	} else if (strncmp(arg, "-audit-interface", alen) == 0) {
	    char *interface = argv[++a];
	    if (osi_audit_interface(interface)) {
		printf("Invalid audit interface '%s'\n", interface);
		PT_EXIT(1);
	    }
	}
	else if (!strncmp(arg, "-rxmaxmtu", alen)) {
	    if ((a + 1) >= argc) {
		fprintf(stderr, "missing argument for -rxmaxmtu\n");
		PT_EXIT(1);
	    }
	    rxMaxMTU = atoi(argv[++a]);
	    if ((rxMaxMTU < RX_MIN_PACKET_SIZE) ||
		 (rxMaxMTU > RX_MAX_PACKET_DATA_SIZE)) {
		printf("rxMaxMTU %d invalid; must be between %d-%" AFS_SIZET_FMT "\n",
			rxMaxMTU, RX_MIN_PACKET_SIZE,
			RX_MAX_PACKET_DATA_SIZE);
		PT_EXIT(1);
	    }
	} 
	else if (*arg == '-') {
	    /* hack in help flag support */

#if defined(SUPERGROUPS)
#ifndef AFS_NT40_ENV
	    printf("Usage: ptserver [-database <db path>] "
		   "[-auditlog <log path>] "
		   "[-audit-interface <file|sysvmq> (default is file)] "
		   "[-syslog[=FACILITY]] [-d <debug level>] "
		   "[-p <number of processes>] [-rebuild] "
		   "[-groupdepth <depth>] "
		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
		   "[-allow-dotted-principals] "
		   "[-enable_peer_stats] [-enable_process_stats] "
		   "[-default_access default_user_access default_group_access] "
		   "[-help]\n");
#else /* AFS_NT40_ENV */
	    printf("Usage: ptserver [-database <db path>] "
		   "[-auditlog <log path>] "
		   "[-audit-interface <file|sysvmq> (default is file)] "
		   "[-d <debug level>] "
		   "[-p <number of processes>] [-rebuild] [-rxbind] "
		   "[-allow-dotted-principals] "
		   "[-default_access default_user_access default_group_access] "
		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
		   "[-groupdepth <depth>] " "[-help]\n");
#endif
#else
#ifndef AFS_NT40_ENV
	    printf("Usage: ptserver [-database <db path>] "
		   "[-auditlog <log path>] "
		   "[-audit-interface <file|sysvmq> (default is file)] "
		   "[-d <debug level>] "
		   "[-syslog[=FACILITY]] "
		   "[-p <number of processes>] [-rebuild] "
		   "[-enable_peer_stats] [-enable_process_stats] "
		   "[-default_access default_user_access default_group_access] "
		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
		   "[-allow-dotted-principals] "
		   "[-help]\n");
#else /* AFS_NT40_ENV */
	    printf("Usage: ptserver [-database <db path>] "
		   "[-auditlog <log path>] [-d <debug level>] "
		   "[-default_access default_user_access default_group_access] "
		   "[-restricted] [-rxmaxmtu <bytes>] [-rxbind] "
		   "[-allow-dotted-principals] "
		   "[-p <number of processes>] [-rebuild] " "[-help]\n");
#endif
#endif
	    fflush(stdout);

	    PT_EXIT(1);
	}
#if defined(SUPERGROUPS)
	else {
	    fprintf(stderr, "Unrecognized arg: '%s' ignored!\n", arg);
	}
#endif
    }

    if (auditFileName) {
	osi_audit_file(auditFileName);
	osi_audit(PTS_StartEvent, 0, AUD_END);
    }

#ifndef AFS_NT40_ENV
    serverLogSyslogTag = "ptserver";
#endif
    OpenLog(AFSDIR_SERVER_PTLOG_FILEPATH);	/* set up logging */
    SetupLogSignals();

    prdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
    if (!prdir) {
	fprintf(stderr, "ptserver: can't open configuration directory.\n");
	PT_EXIT(1);
    }
    if (afsconf_GetNoAuthFlag(prdir))
	printf("ptserver: running unauthenticated\n");

#ifdef AFS_NT40_ENV
    /* initialize winsock */
    if (afs_winsockInit() < 0) {
	ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0);

	fprintf(stderr, "ptserver: couldn't initialize winsock. \n");
	PT_EXIT(1);
    }
#endif
    /* get this host */
    gethostname(hostname, sizeof(hostname));
    th = gethostbyname(hostname);
    if (!th) {
	fprintf(stderr, "ptserver: couldn't get address of this host.\n");
	PT_EXIT(1);
    }
    memcpy(&myHost, th->h_addr, sizeof(afs_uint32));

    /* get list of servers */
    code =
	afsconf_GetExtendedCellInfo(prdir, NULL, "afsprot", &info, clones);
    if (code) {
	afs_com_err(whoami, code, "Couldn't get server list");
	PT_EXIT(2);
    }
    pr_realmName = info.name;

    {
	afs_int32 kvno;		/* see if there is a KeyFile here */
	struct ktc_encryptionKey key;
	code = afsconf_GetLatestKey(prdir, &kvno, &key);
	kerberosKeys = (code == 0);
	if (!kerberosKeys)
	    printf
		("ptserver: can't find any Kerberos keys, code = %d, ignoring\n",
		 code);
    }
    if (kerberosKeys) {
	/* initialize ubik */
	ubik_CRXSecurityProc = afsconf_ClientAuth;
	ubik_CRXSecurityRock = prdir;
	ubik_SRXSecurityProc = afsconf_ServerAuth;
	ubik_SRXSecurityRock = prdir;
	ubik_CheckRXSecurityProc = afsconf_CheckAuth;
	ubik_CheckRXSecurityRock = prdir;
    }
    /* The max needed is when deleting an entry.  A full CoEntry deletion
     * required removal from 39 entries.  Each of which may refers to the entry
     * being deleted in one of its CoEntries.  If a CoEntry is freed its
     * predecessor CoEntry will be modified as well.  Any freed blocks also
     * modifies the database header.  Counting the entry being deleted and its
     * CoEntry this adds up to as much as 1+1+39*3 = 119.  If all these entries
     * and the header are in separate Ubik buffers then 120 buffers may be
     * required. */
    ubik_nBuffers = 120 + /*fudge */ 40;

    if (rxBind) {
	afs_int32 ccode;
	if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || 
	    AFSDIR_SERVER_NETINFO_FILEPATH) {
	    char reason[1024];
	    ccode = parseNetFiles(SHostAddrs, NULL, NULL,
					   ADDRSPERSITE, reason,
					   AFSDIR_SERVER_NETINFO_FILEPATH,
					   AFSDIR_SERVER_NETRESTRICT_FILEPATH);
	} else 
	{
	    ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE);
	}
	if (ccode == 1) {
	    host = SHostAddrs[0];
	    /* the following call is idempotent so if/when it gets called
	     * again by the ubik init stuff, it doesn't really matter
	     * -- klm
	     */
	    rx_InitHost(host, htons(AFSCONF_PROTPORT));
	}
    }

    code =
	ubik_ServerInitByInfo(myHost, htons(AFSCONF_PROTPORT), &info, clones,
			      pr_dbaseName, &dbase);
    if (code) {
	afs_com_err(whoami, code, "Ubik init failed");
	PT_EXIT(2);
    }
#if defined(SUPERGROUPS)
    pt_hook_write();
#endif

    afsconf_BuildServerSecurityObjects(prdir, 0, &securityClasses,
				       &numClasses);

    /* Disable jumbograms */
    rx_SetNoJumbo();

    if (rxMaxMTU != -1) {
	rx_SetMaxMTU(rxMaxMTU);
    }

    tservice =
	rx_NewServiceHost(host, 0, PRSRV, "Protection Server", securityClasses,
		          numClasses, PR_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	fprintf(stderr, "ptserver: Could not create new rx service.\n");
	PT_EXIT(3);
    }
    rx_SetMinProcs(tservice, 2);
    rx_SetMaxProcs(tservice, lwps);
    if (rxkadDisableDotCheck) {
        rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS,
                                    (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
    }

    tservice =
	rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats",
			  securityClasses, numClasses, RXSTATS_ExecuteRequest);
    if (tservice == (struct rx_service *)0) {
	fprintf(stderr, "ptserver: Could not create new rx service.\n");
	PT_EXIT(3);
    }
    rx_SetMinProcs(tservice, 2);
    rx_SetMaxProcs(tservice, 4);

    /* allow super users to manage RX statistics */
    rx_SetRxStatUserOk(pr_rxstat_userok);

    LogCommandLine(argc, argv, "ptserver",
#if defined(SUPERGROUPS)
		   "1.1",
#else
		   "1.0",
#endif
		   "Starting AFS", FSLog);

    rx_StartServer(1);
    osi_audit(PTS_FinishEvent, -1, AUD_END);
    exit(0);
}
Пример #7
0
afs_int32
krb_write_ticket_file(char *realm)
{
    int fd;
    int count;
    afs_int32 code;
    int lifetime, kvno;
    char *tf_name;
    struct ktc_principal client, server;
    struct ktc_token token;

    if ((strlen(realm) >= sizeof(client.cell)))
	return KABADNAME;
    strcpy(server.name, KA_TGS_NAME);
    strcpy(server.instance, realm);
    lcstring(server.cell, realm, sizeof(server.cell));

    code = ktc_GetToken(&server, &token, sizeof(struct ktc_token), &client);
    if (code)
	return code;

    /* Use the KRBTKFILE environment variable if it exists, otherwise fall
     * back upon /tmp/tkt(uid}.
     */
    if ((tf_name = (char *)getenv("KRBTKFILE")))
	fd = open(tf_name, O_WRONLY | O_CREAT | O_TRUNC, 0700);
    else {
	afs_asprintf(&tf_name, "%s/tkt%d", gettmpdir(), getuid());
	if (tf_name == NULL)
	    return ENOMEM;
	fd = open(tf_name, O_WRONLY | O_CREAT | O_TRUNC, 0700);
	free(tf_name);
    }

    if (fd <= 0)
	return errno;

    /* write client name as file header */

    count = strlen(client.name) + 1;
    if (write(fd, client.name, count) != count)
	goto bad;

    count = strlen(client.instance) + 1;
    if (write(fd, client.instance, count) != count)
	goto bad;

    /* Write the ticket and associated data */
    /* Service */
    count = strlen(server.name) + 1;
    if (write(fd, server.name, count) != count)
	goto bad;
    /* Instance */
    count = strlen(server.instance) + 1;
    if (write(fd, server.instance, count) != count)
	goto bad;
    /* Realm */
    ucstring(server.cell, server.cell, sizeof(server.cell));
    count = strlen(server.cell) + 1;
    if (write(fd, server.cell, count) != count)
	goto bad;
    /* Session key */
    if (write(fd, (char *)&token.sessionKey, 8) != 8)
	goto bad;
    /* Lifetime */
    lifetime = time_to_life(token.startTime, token.endTime);
    if (write(fd, (char *)&lifetime, sizeof(int)) != sizeof(int))
	goto bad;
    /* Key vno */
    kvno = token.kvno;
    if (write(fd, (char *)&kvno, sizeof(int)) != sizeof(int))
	goto bad;
    /* Tkt length */
    if (write(fd, (char *)&(token.ticketLen), sizeof(int)) != sizeof(int))
	goto bad;
    /* Ticket */
    count = token.ticketLen;
    if (write(fd, (char *)(token.ticket), count) != count)
	goto bad;
    /* Issue date */
    if (write(fd, (char *)&(token.startTime), sizeof(afs_int32))
	!= sizeof(afs_int32))
	goto bad;
    close(fd);
    return 0;

  bad:
    close(fd);
    return -1;
}
Пример #8
0
int
main(int argc, char **argv)
{
    register afs_int32 code;
    char op[8];
    char name[PR_MAXNAMELEN];
    afs_int32 id, oid = ANONYMOUSID, gid;
    afs_int32 pos;
    unsigned int i;
    int n;
    struct prentry entry;
    prlist alist;
    idlist lid;
    namelist lnames;
    struct hostent *hostinfo;
    struct in_addr *hostaddr;
    afs_int32 *ptr;
    char *foo;
    afs_int32 over;
    char *cell;

#ifdef	AFS_AIX32_ENV
    /*
     * The following signal action for AIX is necessary so that in case of a 
     * crash (i.e. core is generated) we can include the user's data section 
     * in the core dump. Unfortunately, by default, only a partial core is
     * generated which, in many cases, isn't too useful.
     */
    struct sigaction nsa;

    sigemptyset(&nsa.sa_mask);
    nsa.sa_handler = SIG_DFL;
    nsa.sa_flags = SA_FULLDUMP;
    sigaction(SIGSEGV, &nsa, NULL);
#endif
    whoami = argv[0];

    initialize_PT_error_table();

    strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH);
    cell = 0;
    n = 1;
    while (n < argc) {
	int arglen = strlen(argv[n]);
	char arg[256];
	lcstring(arg, argv[n], sizeof(arg));
#define IsArg(a) (strncmp (arg,a, arglen) == 0)
	if (IsArg("-testconfdir"))
	    strncpy(confdir, argv[++n], sizeof(confdir));
	else if (IsArg("client"))
	    strncpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confdir));
	else if (IsArg("server"))
	    strncpy(confdir, AFSDIR_SERVER_ETC_DIRPATH, sizeof(confdir));
	else if (IsArg("0") || IsArg("1") || IsArg("2"))
	    security = atoi(argv[n]);
	else if (IsArg("-ignoreexist"))
	    ignoreExist++;
	else if (IsArg("-cell"))
	    cell = argv[++n];
	else {
	    printf
		("Usage is: 'prclient [-testconfdir <dir> | server | client] [0 | 1 | 2] [-ignoreExist] [-cell <cellname>]\n");
	    exit(1);
	}
	n++;
    }

    printf("Using CellServDB file in %s\n", confdir);
    if (security == 0)
	printf("Making unauthenticated connection to prserver\n");

    code = pr_Initialize(security, confdir, cell);
    if (code) {
	afs_com_err(whoami, code, "Couldn't initialize protection library");
	exit(1);
    }

    while (1) {
	char *s;

	printf("pr> ");
	s = fgets(line, sizeof(line), stdin);
	if (s == NULL)
	    break;
	lineProgress = 0;

	code = GetString(op, sizeof(op));
	if (code) {
	    afs_com_err(whoami, PRBADARG,
		    "error reading opcode in line '%s', got '%.*s'", line,
		    sizeof(op), op);
	    exit(1);
	}
	if (strlen(op) == 0)
	    continue;		/* no input */

	if (!strcmp(op, "cr")) {
	    if (GetString(name, sizeof(name)) || GetInt32(&id)
		|| GetInt32(&oid))
		code = PRBADARG;
	    /* use ubik_Call to do the work, finding an up server and handling
	     * the job of finding a sync site, if need be */
	    else
		code = ubik_PR_INewEntry(pruclient, 0, name, id, oid);
	    if (CodeOk(code))
		afs_com_err(whoami, code, "on %s %s %d %d", op, name, id, oid);
	} else if (!strcmp(op, "sf")) {
	    afs_int32 mask, access, gq, uq;
	    if (GetInt32(&id) || GetXInt32(&mask) || GetXInt32(&access)
		|| GetInt32(&gq) || GetInt32(&uq))
		code = PRBADARG;
	    else
		code =
		    ubik_PR_SetFieldsEntry(pruclient, 0, id, mask,
			      access, gq, uq, 0, 0);
	    if (CodeOk(code))
		afs_com_err(whoami, code, "on %s %d %x %x %d %d", op, id, mask,
			access, gq, uq);
	} else if (!strcmp(op, "ce")) {
	    char newname[PR_MAXNAMELEN];
	    afs_int32 newid;
	    if (GetInt32(&id) || GetString(newname, sizeof(newname))
		|| GetInt32(&oid) || GetInt32(&newid))
		code = PRBADARG;
	    else
		code =
		    ubik_PR_ChangeEntry(pruclient, 0, id, newname, oid,
			      newid);
	    if (CodeOk(code))
		afs_com_err(whoami, code, "on %s %d %s %d %d", op, id, newname,
			oid, newid);
	} else if (!strcmp(op, "wh")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_WhereIsIt(pruclient, 0, id, &pos);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    else
		printf("location %d\n", pos);
	} else if (!strcmp(op, "du")) {
	    memset(&entry, 0, sizeof(entry));
	    /* scanf("%d",&pos); */
	    if (GetInt32(&pos))
		code = PRBADARG;
	    else
		code = ubik_PR_DumpEntry(pruclient, 0, pos, (struct prdebugentry *)&entry);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		PrintEntry(pos, &entry, /*indent */ 0);
#if 0
		printf("The contents of the entry for %d are:\n", entry.id);
		printf("flags %d next %d\n", entry.flags, entry.next);
		printf("Groups (or members) \n");
		for (i = 0; i < PRSIZE; i++)
		    printf("%d\n", entry.entries[i]);
		printf("nextID %d nextname %d name %s\n", entry.nextID,
		       entry.nextName, entry.name);
		printf("owner %d creator %d\n", entry.owner, entry.creator);
#endif
	    }
	} else if (!strcmp(op, "add") || !strcmp(op, "au")) {
	    /* scanf("%d %d",&id,&gid); */
	    if (GetInt32(&id) || GetInt32(&gid))
		code = PRBADARG;
	    else
		code = ubik_PR_AddToGroup(pruclient, 0, id, gid);
	    if (CodeOk(code))
		afs_com_err(whoami, code, "on %s %d %d", op, id, gid);
	} else if (!strcmp(op, "iton")) {
	    lid.idlist_val = (afs_int32 *) malloc(20 * sizeof(afs_int32));
	    ptr = lid.idlist_val;
	    lid.idlist_len = 0;
	    foo = line;
	    skip(&foo);
	    while ((lid.idlist_len < 20) && (sscanf(foo, "%d", ptr) != EOF)) {
		lid.idlist_len++;
		skip(&foo);
		ptr++;
	    }
	    if (*foo) {
		fprintf(stderr, "too many values specified; max is %d\n", 20);
	    }
	    lnames.namelist_val = 0;
	    lnames.namelist_len = 0;
	    code = ubik_PR_IDToName(pruclient, 0, &lid, &lnames);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		for (i = 0; i < lnames.namelist_len; i++) {
		    printf("id %d name %s\n", lid.idlist_val[i],
			   lnames.namelist_val[i]);
		}
		free(lnames.namelist_val);
	    }
	    free(lid.idlist_val);
	    lid.idlist_val = 0;
	    lid.idlist_len = 0;
	} else if (!strcmp(op, "ntoi")) {
	    lnames.namelist_val =
		(prname *) malloc(PR_MAXLIST * PR_MAXNAMELEN);
	    lnames.namelist_len = 0;
	    foo = line;
	    skip(&foo);
	    for (i = 0; ((lnames.namelist_len < PR_MAXLIST)
			 && (sscanf(foo, "%s", lnames.namelist_val[i]) !=
			     EOF)); i++) {
		lnames.namelist_len++;
		skip(&foo);
	    }
	    if (*foo) {
		fprintf(stderr, "too many values specified; max is %d\n",
			PR_MAXLIST);
	    }
	    lid.idlist_val = 0;
	    lid.idlist_len = 0;
	    code = ubik_PR_NameToID(pruclient, 0, &lnames, &lid);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		for (i = 0; i < lid.idlist_len; i++)
		    printf("name %s id %d\n", lnames.namelist_val[i],
			   lid.idlist_val[i]);
		free(lid.idlist_val);
	    }
	    free(lnames.namelist_val);
	    lnames.namelist_val = 0;
	    lnames.namelist_len = 0;
	} else if (!strcmp(op, "del")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_Delete(pruclient, 0, id);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	} else if (!strcmp(op, "dg")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_Delete(pruclient, 0, id);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	} else if (!strcmp(op, "rm")) {
	    /* scanf("%d %d",&id,&gid); */
	    if (GetInt32(&id) || GetInt32(&gid))
		code = PRBADARG;
	    else
		code = ubik_PR_RemoveFromGroup(pruclient, 0, id, gid);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	}
#if defined(SUPERGROUPS)
	else if (!strcmp(op, "lsg")) {
	    alist.prlist_len = 0;
	    alist.prlist_val = 0;
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code =
		    ubik_PR_ListSuperGroups(pruclient, 0, id, &alist,
			      &over);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		ptr = alist.prlist_val;
		if (over) {
		    printf("Number of groups greater than PR_MAXGROUPS!\n");
		    printf("Excess of %d.\n", over);
		}
		for (i = 0; i < alist.prlist_len; i++, ptr++)
		    printf("%d\n", *ptr);
		free(alist.prlist_val);
		alist.prlist_len = 0;
		alist.prlist_val = 0;
	    }
	}
#endif /* SUPERGROUPS */
	else if (!strcmp(op, "l")) {
	    alist.prlist_len = 0;
	    alist.prlist_val = 0;
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_GetCPS(pruclient, 0, id, &alist, &over);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		ptr = alist.prlist_val;
		if (over) {
		    printf("Number of groups greater than PR_MAXGROUPS!\n");
		    printf("Excess of %d.\n", over);
		}
		for (i = 0; i < alist.prlist_len; i++, ptr++)
		    printf("%d\n", *ptr);
		free(alist.prlist_val);
		alist.prlist_len = 0;
		alist.prlist_val = 0;
	    }
	} else if (!strcmp(op, "lh")) {
	    alist.prlist_len = 0;
	    alist.prlist_val = 0;
	    /* scanf("%d",&id); */
	    if (GetString(name, sizeof(name)))
		code = PRBADARG;
	    else if (!(hostinfo = gethostbyname(name)))
		code = PRBADARG;
	    else {
		hostaddr = (struct in_addr *)hostinfo->h_addr_list[0];
		id = ntohl(hostaddr->s_addr);
		code =
		    ubik_PR_GetHostCPS(pruclient, 0, id, &alist, &over);
	    }
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		ptr = alist.prlist_val;
		if (over) {
		    printf("Number of groups greater than PR_MAXGROUPS!\n");
		    printf("Excess of %d.\n", over);
		}
		for (i = 0; i < alist.prlist_len; i++, ptr++)
		    printf("%d\n", *ptr);
		free(alist.prlist_val);
		alist.prlist_len = 0;
		alist.prlist_val = 0;
	    }
	}
#if defined(SUPERGROUPS)
	else if (!strcmp(op, "m")) {
	    alist.prlist_len = 0;
	    alist.prlist_val = 0;
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code =
		    ubik_PR_ListElements(pruclient, 0, id, &alist,
			      &over);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS) {
		ptr = alist.prlist_val;
		if (over) {
		    printf("Number of groups greater than PR_MAXGROUPS!\n");
		    printf("Excess of %d.\n", over);
		}
		for (i = 0; i < alist.prlist_len; i++, ptr++)
		    printf("%d\n", *ptr);
		free(alist.prlist_val);
		alist.prlist_len = 0;
		alist.prlist_val = 0;
	    }
	}
#endif /* SUPERGROUPS */
	else if (!strcmp(op, "nu")) {
	    /* scanf("%s",name); */
	    if (GetString(name, sizeof(name)))
		code = PRBADARG;
	    else
		code = pr_CreateUser(name, &id);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS)
		printf("Id is %d.\n", id);
	} else if (!strcmp(op, "ng")) {
	    /* scanf("%s",name); */
	    if (GetString(name, sizeof(name)))
		code = PRBADARG;
	    else
		code = ubik_PR_NewEntry(pruclient, 0, name, 1, oid, &id);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS)
		printf("Id is %d.\n", id);
	} else if (!strcmp(op, "lm")) {
	    code = ubik_PR_ListMax(pruclient, 0, &id, &gid);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS)
		printf("Max user id is %d, max (really min) group is %d.\n",
		       id, gid);
	} else if (!strcmp(op, "smu")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_SetMax(pruclient, 0, id, 0);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	} else if (!strcmp(op, "smg")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = ubik_PR_SetMax(pruclient, 0, id, 1);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	} else if (!strcmp(op, "sin")) {
	    /* scanf("%d",&id); */
	    if (GetInt32(&id))
		code = PRBADARG;
	    else
		code = pr_SIdToName(id, name);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS)
		printf("id %d name %s\n", id, name);
	} else if (!strcmp(op, "sni")) {
	    /* scanf("%s",name); */
	    if (GetString(name, sizeof(name)))
		code = PRBADARG;
	    else
		code = pr_SNameToId(name, &id);
	    if (CodeOk(code))
		printf("%s\n", pr_ErrorMsg(code));
	    if (code == PRSUCCESS)
		printf("name %s id %d\n", name, id);
	} else if (!strcmp(op, "fih")) {
	    char tname[128];
	    struct PrUpdateEntry uentry;
	    memset(&uentry, 0, sizeof(uentry));
	    /* scanf("%s",name); */
	    if (GetString(name, sizeof(name))) {
		code = PRBADARG;
		continue;
	    }
	    code = pr_SNameToId(name, &id);
	    if (CodeOk(code)) {
		printf("%s\n", pr_ErrorMsg(code));
		continue;
	    }
	    code = pr_SIdToName(id, tname);
	    if (code == PRSUCCESS) {
		printf
		    ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
		     name, id);
/*		continue;*/
	    }
	    uentry.Mask = PRUPDATE_IDHASH;
	    code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry);
	    if (code) {
		printf("Failed to update entry %s (err=%d)\n", name, code);
		continue;
	    }
	} else if (!strcmp(op, "fnh")) {
	    int tid;
	    struct PrUpdateEntry uentry;
	    memset(&uentry, 0, sizeof(uentry));
	    /* scanf("%d", &id); */
	    if (GetInt32(&id)) {
		code = PRBADARG;
		continue;
	    }
	    code = pr_SIdToName(id, name);
	    if (CodeOk(code)) {
		printf("%s\n", pr_ErrorMsg(code));
		continue;
	    }
	    code = pr_SNameToId(name, &tid);
	    if (code == PRSUCCESS) {
		printf
		    ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
		     id, name);
/*		continue;*/
	    }
	    uentry.Mask = PRUPDATE_NAMEHASH;
	    code =
		ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry);
	    if (code) {
		printf("Failed to update entry with id %d (err=%d)\n", id,
		       code);
		continue;
	    }
	}
#if defined(SUPERGROUPS)
	else if (!strcmp(op, "fih")) {
	    char tname[128];
	    struct PrUpdateEntry uentry;
	    memset(&uentry, 0, sizeof(uentry));
	    /* scanf("%s",name); */
	    if (GetString(name, sizeof(name))) {
		code = PRBADARG;
		continue;
	    }
	    code = pr_SNameToId(name, &id);
	    if (CodeOk(code)) {
		printf("%s\n", pr_ErrorMsg(code));
		continue;
	    }
	    code = pr_SIdToName(id, tname);
	    if (code == PRSUCCESS) {
		printf
		    ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
		     name, id);
/*		continue;*/
	    }
	    uentry.Mask = PRUPDATE_IDHASH;
	    code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry);
	    if (code) {
		printf("Failed to update entry %s (err=%d)\n", name, code);
		continue;
	    }
	} else if (!strcmp(op, "fnh")) {
	    int tid;
	    struct PrUpdateEntry uentry;
	    memset(&uentry, 0, sizeof(uentry));
	    /* scanf("%d", &id); */
	    if (GetInt32(&id)) {
		code = PRBADARG;
		continue;
	    }
	    code = pr_SIdToName(id, name);
	    if (CodeOk(code)) {
		printf("%s\n", pr_ErrorMsg(code));
		continue;
	    }
	    code = pr_SNameToId(name, &tid);
	    if (code == PRSUCCESS) {
		printf
		    ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
		     id, name);
/*		continue;*/
	    }
	    uentry.Mask = PRUPDATE_NAMEHASH;
	    code =
		ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry);
	    if (code) {
		printf("Failed to update entry with id %d (err=%d)\n", id,
		       code);
		continue;
	    }
	}
#endif /* SUPERGROUPS */
	else if (!strcmp(op, "?"))
	    PrintHelp();
	else if (!strcmp(op, "q"))
	    exit(0);
	else
	    printf("Unknown op: '%s'! ? for help\n", op);
    }
}
Пример #9
0
int
CommandProc(struct cmd_syndesc *as, void *arock)
{
    char name[MAXKTCNAMELEN] = "";
    char instance[MAXKTCNAMELEN] = "";
    char cell[MAXKTCREALMLEN] = "";
    char realm[MAXKTCREALMLEN] = "";
    afs_int32 serverList[MAXSERVERS];
    char *lcell;		/* local cellname */
    int code;
    int i;

    struct ubik_client *conn = 0;
    struct ktc_encryptionKey key;
    struct ktc_encryptionKey mitkey;
    struct ktc_encryptionKey newkey;
    struct ktc_encryptionKey newmitkey;

    struct ktc_token token;

    struct passwd pwent;
    struct passwd *pw = &pwent;

    int insist;			/* insist on good password quality */
    int lexplicit = 0;		/* servers specified explicitly */
    int local;			/* explicit cell is same a local cell */
    int foundPassword = 0;	/*Not yet, anyway */
    int foundNewPassword = 0;	/*Not yet, anyway */
    int foundExplicitCell = 0;	/*Not yet, anyway */
#ifdef DEFAULT_MITV4_STRINGTOKEY
    int dess2k = 1;
#elif DEFAULT_AFS_STRINGTOKEY
    int dess2k = 0;
#else
    int dess2k = -1;
#endif

    /* blow away command line arguments */
    for (i = 1; i < zero_argc; i++)
	memset(zero_argv[i], 0, strlen(zero_argv[i]));
    zero_argc = 0;

    /* first determine quiet flag based on -pipe switch */
    Pipe = (as->parms[aPIPE].items ? 1 : 0);

#if TIMEOUT
    signal(SIGALRM, timedout);
    alarm(30);
#endif

    code = ka_Init(0);
    if (code || !(lcell = ka_LocalCell())) {
#ifndef AFS_FREELANCE_CLIENT
	if (!Pipe)
	    afs_com_err(rn, code, "Can't get local cell name!");
	exit(1);
#endif
    }

    code = rx_Init(0);
    if (code) {
	if (!Pipe)
	    afs_com_err(rn, code, "Failed to initialize Rx");
	exit(1);
    }

    strcpy(instance, "");

    /* Parse our arguments. */

    if (as->parms[aCELL].items) {
	/*
	 * cell name explicitly mentioned; take it in if no other cell name
	 * has already been specified and if the name actually appears.  If
	 * the given cell name differs from our own, we don't do a lookup.
	 */
	foundExplicitCell = 1;
	strncpy(realm, as->parms[aCELL].items->data, sizeof(realm));
    }

    if (as->parms[aSERVERS].items) {
	/* explicit server list */
	int i;
	struct cmd_item *ip;
	char *ap[MAXSERVERS + 2];

	for (ip = as->parms[aSERVERS].items, i = 2; ip; ip = ip->next, i++)
	    ap[i] = ip->data;
	ap[0] = "";
	ap[1] = "-servers";
	code = ubik_ParseClientList(i, ap, serverList);
	if (code) {
	    if (!Pipe)
		afs_com_err(rn, code, "could not parse server list");
	    return code;
	}
	lexplicit = 1;
    }

    if (as->parms[aPRINCIPAL].items) {
	ka_ParseLoginName(as->parms[aPRINCIPAL].items->data, name, instance,
			  cell);
	if (strlen(instance) > 0)
	    if (!Pipe)
		fprintf(stderr,
			"Non-null instance (%s) may cause strange behavior.\n",
			instance);
	if (strlen(cell) > 0) {
	    if (foundExplicitCell) {
		if (!Pipe)
		    fprintf(stderr,
			    "%s: May not specify an explicit cell twice.\n",
			    rn);
		return -1;
	    }
	    foundExplicitCell = 1;
	    strncpy(realm, cell, sizeof(realm));
	}
	pw->pw_name = name;
    } else {
	/* No explicit name provided: use Unix uid. */
#ifdef AFS_NT40_ENV
	userNameLen = 128;
	if (GetUserName(userName, &userNameLen) == 0) {
	    if (!Pipe) {
		fprintf(stderr,
			"Can't figure out your name in local cell %s from your user id.\n",
			lcell);
		fprintf(stderr, "Try providing the user name.\n");
	    }
	    exit(1);
	}
	pw->pw_name = userName;
#else
	pw = getpwuid(getuid());
	if (pw == 0) {
	    if (!Pipe) {
		fprintf(stderr,
			"Can't figure out your name in local cell %s from your user id.\n",
			lcell);
		fprintf(stderr, "Try providing the user name.\n");
	    }
	    exit(1);
	}
#endif
    }

    if (as->parms[aPASSWORD].items) {
	/*
	 * Current argument is the desired password string.  Remember it in
	 * our local buffer, and zero out the argument string - anyone can
	 * see it there with ps!
	 */
	foundPassword = 1;
	strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd));
	memset(as->parms[aPASSWORD].items->data, 0,
	       strlen(as->parms[aPASSWORD].items->data));
    }

    if (as->parms[aNEWPASSWORD].items) {
	/*
	 * Current argument is the new password string.  Remember it in
	 * our local buffer, and zero out the argument string - anyone can
	 * see it there with ps!
	 */
	foundNewPassword = 1;
	strncpy(npasswd, as->parms[aNEWPASSWORD].items->data,
		sizeof(npasswd));
	memset(as->parms[aNEWPASSWORD].items->data, 0,
	       strlen(as->parms[aNEWPASSWORD].items->data));
    }
#ifdef AFS_FREELANCE_CLIENT
    if (!foundExplicitCell && !lcell) {
	if (!Pipe)
	    afs_com_err(rn, code, "no cell name provided");
	exit(1);
    }
#else
    if (!foundExplicitCell)
	strcpy(realm, lcell);
#endif /* freelance */

    if ((code = ka_CellToRealm(realm, realm, &local))) {
	if (!Pipe)
	    afs_com_err(rn, code, "Can't convert cell to realm");
	exit(1);
    }
    lcstring(cell, realm, sizeof(cell));

    ka_PrintUserID("Changing password for '", pw->pw_name, instance, "'");
    printf(" in cell '%s'.\n", cell);

    /* Get the password if it wasn't provided. */
    if (!foundPassword) {
	if (Pipe)
	    getpipepass(passwd, sizeof(passwd));
	else {
	    code = read_pass(passwd, sizeof(passwd), "Old password: "******"reading password");
		exit(1);
	    }
	}
    }
    ka_StringToKey(passwd, realm, &key);
    des_string_to_key(passwd, ktc_to_cblockptr(&mitkey));
    give_to_child(passwd);

    /* Get new password if it wasn't provided. */
    insist = 0;
    if (!foundNewPassword) {
	if (Pipe)
	    getpipepass(npasswd, sizeof(npasswd));
	else {
	    do {
		code =
		    read_pass(npasswd, sizeof(npasswd),
			      "New password (RETURN to abort): ", 0);
		if (code || (strlen(npasswd) == 0)) {
		    if (code)
			code = KAREADPW;
		    goto no_change;

		}
	    } while (password_bad(npasswd));

	    code =
		read_pass(verify, sizeof(verify), "Retype new password: "******"Mismatch - ");
		goto no_change;
	    }
	    memset(verify, 0, sizeof(verify));
	}
    }
    if ((code = password_bad(npasswd))) {	/* assmt here! */
	goto no_change_no_msg;
    }
#if TRUNCATEPASSWORD
    if (strlen(npasswd) > 8) {
	npasswd[8] = 0;
	fprintf(stderr,
		"%s: password too long, only the first 8 chars will be used.\n",
		rn);
    } else
	npasswd[8] = 0;		/* in case the password was exactly 8 chars long */
#endif
    ka_StringToKey(npasswd, realm, &newkey);
    des_string_to_key(npasswd, ktc_to_cblockptr(&newmitkey));
    memset(npasswd, 0, sizeof(npasswd));

    if (lexplicit)
	ka_ExplicitCell(realm, serverList);

    /* Get an connection to kaserver's admin service in desired cell.  Set the
     * lifetime above the time uncertainty so that badly skewed clocks are
     * reported when the ticket is decrypted.  Then give us 10 seconds to
     * actually get our work done if the clocks are skewed by only 14:59.
     * NOTE: Kerberos lifetime encoding will round this up to next 5 minute
     * interval, namely 20 minutes. */

#define ADMIN_LIFETIME (KTC_TIME_UNCERTAINTY+1)

    code =
	ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME,
			 &token, /*!new */ 0);
    if (code == KABADREQUEST) {
	code =
	    ka_GetAdminToken(pw->pw_name, instance, realm, &mitkey,
			     ADMIN_LIFETIME, &token, /*!new */ 0);
	if ((code == KABADREQUEST) && (strlen(passwd) > 8)) {
	    /* try with only the first 8 characters incase they set their password
	     * with an old style passwd program. */
	    char pass8[9];
	    strncpy(pass8, passwd, 8);
	    pass8[8] = 0;
	    ka_StringToKey(pass8, realm, &key);
	    memset(pass8, 0, sizeof(pass8));
	    memset(passwd, 0, sizeof(passwd));
	    code = ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME, &token,	/*!new */
				    0);
#ifdef notdef
	    /* the folks in testing really *hate* this message */
	    if (code == 0) {
		fprintf(stderr,
			"Warning: only the first 8 characters of your old password were significant.\n");
	    }
#endif
	    if (code == 0) {
		if (dess2k == -1)
		    dess2k = 0;
	    }
	} else {
	    if (dess2k == -1)
		dess2k = 1;
	}
    } else {
	if (dess2k == -1)
	    dess2k = 0;
    }

    memset(&mitkey, 0, sizeof(mitkey));
    memset(&key, 0, sizeof(key));
    if (code == KAUBIKCALL)
	afs_com_err(rn, code, "(Authentication Server unavailable, try later)");
    else if (code) {
	if (code == KABADREQUEST)
	    fprintf(stderr, "%s: Incorrect old password.\n", rn);
	else
	    afs_com_err(rn, code, "so couldn't change password");
    } else {
	code =
	    ka_AuthServerConn(realm, KA_MAINTENANCE_SERVICE, &token, &conn);
	if (code)
	    afs_com_err(rn, code, "contacting Admin Server");
	else {
	    if (dess2k == 1)
		code =
		    ka_ChangePassword(pw->pw_name, instance, conn, 0,
				      &newmitkey);
	    else
		code =
		    ka_ChangePassword(pw->pw_name, instance, conn, 0,
				      &newkey);
	    memset(&newkey, 0, sizeof(newkey));
	    memset(&newmitkey, 0, sizeof(newmitkey));
	    if (code) {
		char *reason;
		reason = (char *)afs_error_message(code);
		fprintf(stderr, "%s: Password was not changed because %s\n",
			rn, reason);
	    } else
		printf("Password changed.\n\n");
	}
    }
    memset(&newkey, 0, sizeof(newkey));
    memset(&newmitkey, 0, sizeof(newmitkey));

    /* Might need to close down the ubik_Client connection */
    if (conn) {
	ubik_ClientDestroy(conn);
	conn = 0;
    }
    rx_Finalize();
    terminate_child();
    exit(code);

  no_change:			/* yuck, yuck, yuck */
    if (code)
	afs_com_err(rn, code, "getting new password");
  no_change_no_msg:
    memset(&key, 0, sizeof(key));
    memset(npasswd, 0, sizeof(npasswd));
    printf("Password for '%s' in cell '%s' unchanged.\n\n", pw->pw_name,
	   cell);
    terminate_child();
    exit(code ? code : 1);
}