예제 #1
0
static int hash_password (
    uaf_qword *output_hash,
    string *password,
    unsigned char encrypt,
    unsigned short salt,
    string *username)
{
    string	    *r3;	/* Holds descriptors for COLLAPSE_R2 */
    quad	    *r4;	/* Address of the output buffer */
    uaf_lword   r5;		/* Length of username */
    char	r7 = 0,		/* Flag for encryption method # 3 */
            *bytptr;	/* Pointer for adding in random salt */
    quad	qword;		/* Quadword form of the output buffer */
    char	uname[13];	/* buffer for padded username (PURDY) */

    /* ------------------------------------------------------------------------ */


    /* Check for invalid parameters */
    if ((encrypt < 1) || (encrypt > 3)) {
        puts("BAD BAD!");
        return -1;
//         exit(SS$_BADPARAM);
    }
    if (username->dsc$w_length > 31) {
        puts("2");
        printf("Internal coding error, username is more than 31 bytes long.\n");
        exit(SS$_ABORT);
    }


    /* Setup pointer references */
    r3 = password;			/* 1st COLLAPSE uses the password desc.   */
    r4 = &qword;			/* @r4..@r4+7 equals obuf */
    r5 = username->dsc$w_length;
    r7 = (encrypt == 3);

    /* Clear the output buffer (zero the quadword) */
    r4->ulw[0] = 0;
    r4->ulw[1] = 0;
    UAF_QW_SET(*output_hash,0);

    /* Check for the null password and return zero as the hash value if so */
    if (password->dsc$w_length == 0) {
        return SS$_NORMAL;
    }

    switch (encrypt) {
        int ulen;
    case UAI$C_AD_II:		/* CRC algorithm with Autodin II poly */
        /* As yet unsupported */
        return SS$_BADPARAM;

    case UAI$C_PURDY:		/* Purdy algorithm */

        /* Use a blank padded username */
        strncpy(uname,"            ",sizeof(uname));
        strncpy(uname, username->dsc$a_pointer, r5);
        username->dsc$a_pointer = (char *)&uname;
        username->dsc$w_length = 12;
        break;

    case UAI$C_PURDY_V:		/* Purdy with blanks stripped */
    case UAI$C_PURDY_S:		/* Hickory algorithm; Purdy_V with rotation */

        /* Check padding.  Don't count blanks in the string length.
        * Remember:  r6->username_descriptor   the first word is length, then
        * 2 bytes of class information (4 bytes total), then the address of the
        * buffer.  Usernames can not be longer than 31 characters.
        */
        for ( ulen = username->dsc$w_length; ulen > 0; ulen-- ) {
            if ( username->dsc$a_pointer[ulen-1] != ' ' ) break;
            username->dsc$w_length--;
        }

        /* If Purdy_S:  Bytes 0-1 => plaintext length */
        if (r7) {
            r4->ulw[0] = password->dsc$w_length;
        }

        break;
    }


    /* Collapse the password to a quadword U; buffer pointed to by r4 */
    COLLAPSE_R2 (r3, r4, r7);
    /* r3 already points to password descriptor */


    /* Add random salt into the middle of U */
    /* This has to be done byte-wise because the Sun will not allow you */
    /* to add unaligned words, or it will give you a bus error and core dump :) */
    bytptr = &r4->b[3+1];
    *bytptr += (char)(salt>>8);			/* Add the high byte */

    /* Check for carry out of the low byte */
    bytptr--;
    if ( (short)((unsigned char)*bytptr + (unsigned char)(salt & 0xff)) > 255) {
        *(bytptr + 1) += 1;			/* Account for the carry */
    }
    *bytptr += (char)(salt & 0xff);			/* Add the low byte */



    /* Collapse the username into the quadword */
    r3 = username;		/* Point r3 to the valid username desriptor */
    COLLAPSE_R2 (r3, r4, r7);

    /* U (qword) contains the 8 character output buffer in quadword format */

    /* Run U through the polynomial mod P */
    Purdy (r4);

    /* Write qword (*r4) back into the output buffer */
    *((quad *) output_hash) = qword;

    /* Normal exit */
    return SS$_NORMAL;

} /* LGI$HPWD */
예제 #2
0
static void process_file(char *infile)
{
	int i, status, lnum, is_raw;
	FILE *listf, *rawf;
	char line[4096], *lf, *username, *suffix, *directory, *prefix;
	char encoded[UAF_ENCODE_SIZE], *result;

	struct uaf_hash_info pwd, pwd2;
	struct uaf_account_info acct;
	struct uaf_rec rec;	/* raw record */
	uaf_qword null_hash;

	is_raw = 1;
#ifdef VMS
	if (strcmp(infile, "$") == 0) {
		is_raw = 0;
		infile = "SYSUAF.LIS";
		spawn_authorize(infile);
	} else if (infile[0] == '~') {
		is_raw = 0;
		infile = "useruaf.lis";
		single_user(infile, &argv[1][1]);
	} else if ((infile[0] != '/') && (0 != strncmp(infile, "./", 2))) {
		is_raw = 0;
	}
#endif
	if (is_raw) {
		rawf = fopen(infile, "rb");
		listf = (FILE *) 0;
	} else {
		listf = fopen(infile, "r");
		rawf = (FILE *) 0;
	}
	if (!listf && !rawf) {
		fprintf(stderr, "File open failure on '%s'\n", infile);
		if (rawf) fclose(rawf);
		return;
	}

	/*
	 * Convert each input line to a corresponding passwd file line.
	 */
	uaf_init();
	UAF_QW_SET(null_hash, 0);
	lnum = 0;
	while (1) {
		char *priv_summary;
		if (is_raw) {
			/*
			 * Input file is raw UAF file records, call function in uaf_encode
			 * module to extract passwword and other information.
			 */
			if (1 != fread(&rec, sizeof(rec), 1, rawf))
				break;
			status =
			    uaf_extract_from_raw(&rec, sizeof(rec), &pwd,
			    &pwd2, &acct, &prefix, &priv_summary);
		} else {
			/*
			 * Input is a authorize utility brief listing, trim carriage control.
			 */
			if (!fgets(line, sizeof(line), listf))
				break;
			lf = strchr(line, '\n');
			if (lf)
				*lf = '\0';
			lnum++;
			if (strlen(line) < 21)
				continue;	/* line too short, ignore */
			/*
			 * Extract summary data and username from line.
			 */
			prefix = "";
			if (strlen(line) > 69) {
				directory = &line[69];
				if (strcmp(directory, "Disuser") == 0)
					prefix = "/disuser";
				if (strcmp(directory, "Expired") == 0)
					prefix = "/expired";
			}
			if (strlen(line) > 59) {
				priv_summary = &line[59];
				for (i = 0; priv_summary[i]; i++) {
					if (priv_summary[i] == ' ') {
						priv_summary[i] = '\0';
						break;
					}
				}
			} else {
				priv_summary = "unknown";
			}
			username = &line[21];
			for (i = 0; username[i]; i++) {
				if (username[i] == ' ') {
					username[i] = '\0';
					break;
				}
			}
			/*
			 * Use $GETUAI to get info needed to populate fields of passwd file
			 * line.  Be lazy and use dummy string for home_dir (to avoid dealing
			 * with colon in VMS file specification).
			 */
			if (strcmp(username, "Username") == 0)
				continue;	/* header line */
			status = uaf_getuai_info(username, &pwd, &pwd2, &acct);
		}
		if (status & 1) {
			/*
			 * Output user data as passwd-like text line.
			 */
			if (UAF_QW_EQL(pwd2.hash, null_hash))
				suffix = "";
			else
				suffix = ".1";	/* flag as primary of 2 */

			result = uaf_hash_encode(&pwd, encoded);

			fprintf(stdout, "%s%s:%s:%d:%d:%s:/%s%s%s/%s:%s\n",
			    colon_blow(pwd.username.s), suffix,
			    result,
			    acct.uic[0],
			    acct.uic[1],
			    colon_blow(acct.owner),
			    (pwd.flags & UAI$M_PWDMIX) ? "Users" : "USERS",
			    prefix[0] ? "/" : "", prefix, priv_summary,
			    colon_blow(acct.shell));
			if (suffix[0] == '.') {
				/*
				 * secondary password present.
				 */
				result = uaf_hash_encode(&pwd2, encoded);
				fprintf(stdout,
				    "%s%s:%s:%d:%d:%s:/%s%s%s/%s:%s\n",
				    colon_blow(pwd.username.s), suffix, result,
				    acct.uic[0], acct.uic[1],
				    colon_blow(acct.owner),
				    (pwd.
					flags & UAI$M_PWDMIX) ? "Users" :
				    "USERS", prefix[0] ? "/" : "", prefix,
				    priv_summary, colon_blow(acct.shell));
			}
		} else {
			fprintf(stderr, "Error fetching UAF information, %s\n", prefix);
			return;
		}
	}

	if (is_raw)
		fclose(rawf);
	else
		fclose(listf);

}