diff options
author | Theodore Tso <tytso@mit.edu> | 1993-06-03 19:29:40 +0000 |
---|---|---|
committer | Theodore Tso <tytso@mit.edu> | 1993-06-03 19:29:40 +0000 |
commit | 746386f12e01102acbe5637aac6f1259c74bb552 (patch) | |
tree | 715df6527f739854dc978c588047607e1907e9e9 /src/lib | |
parent | acbed92e113f54d33789d427e697a23a0f07ab64 (diff) | |
download | krb5-746386f12e01102acbe5637aac6f1259c74bb552.zip krb5-746386f12e01102acbe5637aac6f1259c74bb552.tar.gz krb5-746386f12e01102acbe5637aac6f1259c74bb552.tar.bz2 |
Initial revision
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2611 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
36 files changed, 4989 insertions, 0 deletions
diff --git a/src/lib/.rconf b/src/lib/.rconf new file mode 100644 index 0000000..0be003a --- /dev/null +++ b/src/lib/.rconf @@ -0,0 +1,2 @@ +ignore des.old +ignore FOO diff --git a/src/lib/crypto/des/.rconf b/src/lib/crypto/des/.rconf new file mode 100644 index 0000000..b886964 --- /dev/null +++ b/src/lib/crypto/des/.rconf @@ -0,0 +1,8 @@ +ignore fp.c +ignore ip.c +ignore key_perm.h +ignore odd.h +ignore p.c +ignore p_table.h +ignore s_table.h +ignore doc diff --git a/src/lib/crypto/des/FUNCTIONS b/src/lib/crypto/des/FUNCTIONS new file mode 100644 index 0000000..7ed082e --- /dev/null +++ b/src/lib/crypto/des/FUNCTIONS @@ -0,0 +1,26 @@ +File Function Where? + +weak_key.c mit_des_is_weak_key crypto +string2key.c mit_des_string_to_key ? +random_key.c mit_des_random_key ? +process_ky.c mit_des_process_key ? +new_rn_key.c mit_des_new_random_key ? + mit_des_init_random_number_generator ? + mit_des_set_random_generator_seed ? + mit_des_set_sequence_number ? + mit_des_generate_random_block ? +krb_glue.c mit_des_encrypt_func ? + mit_des_decrypt_func ? +key_sched.c mit_des_key_sched crypto +key_parity.c mit_des_fixup_key_parity crypto + mit_des_check_key_parity crypto +init_rkey.c mit_des_init_random_key crypto +finish_key.c mit_des_finish_key crypto +fin_rndkey.c mit_des_finish_random_key crypto +enc_dec.c mit_des_cbc_encrypt crypto +des.c mit_des_ecb_encrypt crypto +cs_entry.c (var) mit_des_cryptosystem_entry krb5 + (var) krb5_des_cst_entry krb5 + (var) mit_des_cbc_cksumtable_entry krb5 +cksum.c mit_des_cbc_cksum crypto +cbc_cksum.c mit_des_cbc_checksum crypto diff --git a/src/lib/crypto/des/doc/libdes.doc b/src/lib/crypto/des/doc/libdes.doc new file mode 100644 index 0000000..70f9f33 --- /dev/null +++ b/src/lib/crypto/des/doc/libdes.doc @@ -0,0 +1,208 @@ + + How to use the Kerberos encryption library. + + Revised 10/15/85 spm + +1) The following include file is needed: + + /projects/auth/include/des.h (VAX) + --------------- (PC8086) + +2) The encryption library that should be linked to is: + + /projects/auth/lib/libdes.a (VAX) +| /projects/auth/ibm/lib/libdes.a (PC8086 cross-compilation environment) + +3) For each key that may be simultaneously active, + allocate (either compile or malloc) a "Key_schedule" struct, + defined in "des.h" + +4) Create key schedules, as needed, prior to using the encryption + routines, via "des_set_key()". + +5) Setup the input and output areas. Make sure to note the restrictions + on lengths being multiples of eight bytes. + +6) Invoke the encryption/decryption routines, "ecb_encrypt()" + or "cbc_encrypt()" + +7) To generate a cryptographic checksum, use "cbc_cksum()" +/* ---------------------------------------------------------------- */ + + Routine Interfaces-- + +/* ----------------------------------------------------------------- */ + +int + des_set_key(k,schedule) + C_Block *k; + Key_schedule schedule; + + Calculates a key schedule from (all) eight bytes of the input key, and + puts it into the indicated "Key_schedule" struct; + + Make sure to pass valid eight bytes, no padding or other processing + it done. + + The key schedule is then used in subsequent encryption/decryption + operations. Many key schedules may be created and cached for later + use. + + The user is responsible to clear keys and schedules no longer needed + to prevent their disclosure. + +| Checks the parity of the key provided, to make sure it is odd per +| FIPS spec. Returns 0 value for key ok, 1 for key_parity error. + +/* ---------------------------------------------------------------- */ + +int + ecb_encrypt(input,output,schedule,encrypt) + C_Block *input; /* ptr to eight byte input value */ + C_Block *output; /* ptr to eight byte output value */ + int encrypt; /* 0 ==> decrypt, else encrypt */ + Key_schedule schedule; /* addr of key schedule */ + +This is the low level routine that encrypts or decrypts a single 8-byte +block in electronic code book mode. Always transforms the input +data into the output data. + +If encrypt is non-zero, the input (cleartext) is encrypted into the +output (ciphertext) using the specified key_schedule, pre-set via "des_set_key". + +If encrypt is zero, the input (now ciphertext) is decrypted into +the output (now cleartext). + +Input and output may be the same space. + +Does not return any meaningful value. Void is not used for compatibility +with other compilers. + +/* -------------------------------------------------------------- */ + +int + cbc_encrypt(input,output,length,schedule,ivec,encrypt) + + C_Block *input; /* ptr to input data */ + C_Block *output; /* ptr to output data */ + int length; /* desired length, in bytes */ + Key_schedule schedule; /* addr of precomputed schedule */ + C_Block *ivec; /* pointer to 8 byte initialization + * vector + */ + int encrypt /* 0 ==> decrypt; else encrypt*/ + + + If encrypt is non-zero, the routine cipher-block-chain encrypts + the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided + key schedule and initialization vector. If the length is not an integral + multiple of eight bytes, the last block is copied to a temp and zero + filled (highest addresses). The output is ALWAYS an integral multiple + of eight bytes. + + If encrypt is zero, the routine cipher-block chain decrypts the INPUT + (ciphertext) into the OUTPUT (cleartext) using the provided key schedule + and initialization vector. Decryption ALWAYS operates on integral + multiples of 8 bytes, so will round the length provided up to the + appropriate multiple. Consequently, it will always produce the rounded-up + number of bytes of output cleartext. The application must determine if + the output cleartext was zero-padded due to cleartext lengths not integral + multiples of 8. + + No errors or meaningful value are returned. Void is not used for + compatibility with other compilers. + + +/* cbc checksum (MAC) only routine ---------------------------------------- */ +int + cbc_cksum(input,output,length,schedule,ivec) + + C_Block *input; /* >= length bytes of inputtext */ + C_Block *output; /* >= length bytes of outputtext */ + int length; /* in bytes */ + Key_schedule schedule; /* precomputed key schedule */ + C_Block *ivec; /* 8 bytes of ivec */ + + + Produces a cryptographic checksum, 8 bytes, by cipher-block-chain + encrypting the input, discarding the ciphertext output, and only retaining + the last ciphertext 8-byte block. Uses the provided key schedule and ivec. + The input is effectively zero-padded to an integral multiple of + eight bytes, though the original input is not modified. + + No meaningful value is returned. Void is not used for compatibility + with other compilers. + + +/* random_key ----------------------------------------*/ +int + random_key(key) + + C_Block *key; + + The start for the random number generated is set from the current time + in microseconds, then the random number generator is invoked + to create an eight byte output key (not a schedule). The key + generated is set to odd parity per FIPS spec. + + The caller must supply space for the output key, pointed to + by "*key", then after getting a new key, call the des_set_key() + routine when needed. + + No meaningfull value is returned. Void is not used for compatibility + with other compilers. + + +/* string_to_key --------------------------------------------*/ + +int + string_to_key(str,key) + register char *str; + register C_Block *key; + + This routines converts an arbitrary length, null terminated string + to an 8 byte DES key, with each byte parity set to odd, per FIPS spec. + + The algorithm is as follows: + +| Take the first 8 bytes and remove the parity (leaving 56 bits). +| Do the same for the second 8 bytes, and the third, etc. Do this for +| as many sets of 8 bytes as necessary, filling in the remainder of the +| last set with nulls. Fold the second set back on the first (i.e. bit +| 0 over bit 55, and bit 55 over bit 0). Fold the third over the second +| (bit 0 of the third set is now over bit 0 of the first set). Repeat +| until you have done this to all sets. Xor the folded sets. Break the +| result into 8 7 bit bytes, and generate odd parity for each byte. You +| now have 64 bits. Note that DES takes a 64 bit key, and uses only the +| non parity bits. + + +/* read_password -------------------------------------------*/ + +read_password(k,prompt,verify) + C_Block *k; + char *prompt; + int verify; + +This routine issues the supplied prompt, turns off echo, if possible, and +reads an input string. If verify is non-zero, it does it again, for use +in applications such as changing a password. If verify is non-zero, both +versions are compared, and the input is requested repeatedly until they +match. Then, the input string is mapped into a valid DES key, internally +using the string_to_key routine. The newly created key is copied to the +area pointed to by parameter "k". + +No meaningful value is returned. If an error occurs trying to manipulate +the terminal echo, the routine forces the process to exit. + +/* get_line ------------------------*/ +long get_line(p,max) + char *p; + long max; + +Reads input characters from standard input until either a newline appears or +else the max length is reached. The characters read are stuffed into +the string pointed to, which will always be null terminated. The newline +is not inserted in the string. The max parameter includes the byte needed +for the null terminator, so allocate and pass one more than the maximum +string length desired. diff --git a/src/lib/crypto/des/keytest.data b/src/lib/crypto/des/keytest.data new file mode 100644 index 0000000..7ff34ee --- /dev/null +++ b/src/lib/crypto/des/keytest.data @@ -0,0 +1,171 @@ +0101010101010101 95F8A5E5DD31D900 8000000000000000 +0101010101010101 DD7F121CA5015619 4000000000000000 +0101010101010101 2E8653104F3834EA 2000000000000000 +0101010101010101 4BD388FF6CD81D4F 1000000000000000 +0101010101010101 20B9E767B2FB1456 0800000000000000 +0101010101010101 55579380D77138EF 0400000000000000 +0101010101010101 6CC5DEFAAF04512F 0200000000000000 +0101010101010101 0D9F279BA5D87260 0100000000000000 +0101010101010101 D9031B0271BD5A0A 0080000000000000 +0101010101010101 424250B37C3DD951 0040000000000000 +0101010101010101 B8061B7ECD9A21E5 0020000000000000 +0101010101010101 F15D0F286B65BD28 0010000000000000 +0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000 +0101010101010101 E6D5F82752AD63D1 0004000000000000 +0101010101010101 ECBFE3BD3F591A5E 0002000000000000 +0101010101010101 F356834379D165CD 0001000000000000 +0101010101010101 2B9F982F20037FA9 0000800000000000 +0101010101010101 889DE068A16F0BE6 0000400000000000 +0101010101010101 E19E275D846A1298 0000200000000000 +0101010101010101 329A8ED523D71AEC 0000100000000000 +0101010101010101 E7FCE22557D23C97 0000080000000000 +0101010101010101 12A9F5817FF2D65D 0000040000000000 +0101010101010101 A484C3AD38DC9C19 0000020000000000 +0101010101010101 FBE00A8A1EF8AD72 0000010000000000 +0101010101010101 750D079407521363 0000008000000000 +0101010101010101 64FEED9C724C2FAF 0000004000000000 +0101010101010101 F02B263B328E2B60 0000002000000000 +0101010101010101 9D64555A9A10B852 0000001000000000 +0101010101010101 D106FF0BED5255D7 0000000800000000 +0101010101010101 E1652C6B138C64A5 0000000400000000 +0101010101010101 E428581186EC8F46 0000000200000000 +0101010101010101 AEB5F5EDE22D1A36 0000000100000000 +0101010101010101 E943D7568AEC0C5C 0000000080000000 +0101010101010101 DF98C8276F54B04B 0000000040000000 +0101010101010101 B160E4680F6C696F 0000000020000000 +0101010101010101 FA0752B07D9C4AB8 0000000010000000 +0101010101010101 CA3A2B036DBC8502 0000000008000000 +0101010101010101 5E0905517BB59BCF 0000000004000000 +0101010101010101 814EEB3B91D90726 0000000002000000 +0101010101010101 4D49DB1532919C9F 0000000001000000 +0101010101010101 25EB5FC3F8CF0621 0000000000800000 +0101010101010101 AB6A20C0620D1C6F 0000000000400000 +0101010101010101 79E90DBC98F92CCA 0000000000200000 +0101010101010101 866ECEDD8072BB0E 0000000000100000 +0101010101010101 8B54536F2F3E64A8 0000000000080000 +0101010101010101 EA51D3975595B86B 0000000000040000 +0101010101010101 CAFFC6AC4542DE31 0000000000020000 +0101010101010101 8DD45A2DDF90796C 0000000000010000 +0101010101010101 1029D55E880EC2D0 0000000000008000 +0101010101010101 5D86CB23639DBEA9 0000000000004000 +0101010101010101 1D1CA853AE7C0C5F 0000000000002000 +0101010101010101 CE332329248F3228 0000000000001000 +0101010101010101 8405D1ABE24FB942 0000000000000800 +0101010101010101 E643D78090CA4207 0000000000000400 +0101010101010101 48221B9937748A23 0000000000000200 +0101010101010101 DD7C0BBD61FAFD54 0000000000000100 +0101010101010101 2FBC291A570DB5C4 0000000000000080 +0101010101010101 E07C30D7E4E26E12 0000000000000040 +0101010101010101 0953E2258E8E90A1 0000000000000020 +0101010101010101 5B711BC4CEEBF2EE 0000000000000010 +0101010101010101 CC083F1E6D9E85F6 0000000000000008 +0101010101010101 D2FD8867D50D2DFE 0000000000000004 +0101010101010101 06E7EA22CE92708F 0000000000000002 +0101010101010101 166B40B44ABA4BD6 0000000000000001 +8001010101010101 0000000000000000 95A8D72813DAA94D +4001010101010101 0000000000000000 0EEC1487DD8C26D5 +2001010101010101 0000000000000000 7AD16FFB79C45926 +1001010101010101 0000000000000000 D3746294CA6A6CF3 +0801010101010101 0000000000000000 809F5F873C1FD761 +0401010101010101 0000000000000000 C02FAFFEC989D1FC +0201010101010101 0000000000000000 4615AA1D33E72F10 +0180010101010101 0000000000000000 2055123350C00858 +0140010101010101 0000000000000000 DF3B99D6577397C8 +0120010101010101 0000000000000000 31FE17369B5288C9 +0110010101010101 0000000000000000 DFDD3CC64DAE1642 +0108010101010101 0000000000000000 178C83CE2B399D94 +0104010101010101 0000000000000000 50F636324A9B7F80 +0102010101010101 0000000000000000 A8468EE3BC18F06D +0101800101010101 0000000000000000 A2DC9E92FD3CDE92 +0101400101010101 0000000000000000 CAC09F797D031287 +0101200101010101 0000000000000000 90BA680B22AEB525 +0101100101010101 0000000000000000 CE7A24F350E280B6 +0101080101010101 0000000000000000 882BFF0AA01A0B87 +0101040101010101 0000000000000000 25610288924511C2 +0101020101010101 0000000000000000 C71516C29C75D170 +0101018001010101 0000000000000000 5199C29A52C9F059 +0101014001010101 0000000000000000 C22F0A294A71F29F +0101012001010101 0000000000000000 EE371483714C02EA +0101011001010101 0000000000000000 A81FBD448F9E522F +0101010801010101 0000000000000000 4F644C92E192DFED +0101010401010101 0000000000000000 1AFA9A66A6DF92AE +0101010201010101 0000000000000000 B3C1CC715CB879D8 +0101010180010101 0000000000000000 19D032E64AB0BD8B +0101010140010101 0000000000000000 3CFAA7A7DC8720DC +0101010120010101 0000000000000000 B7265F7F447AC6F3 +0101010110010101 0000000000000000 9DB73B3C0D163F54 +0101010108010101 0000000000000000 8181B65BABF4A975 +0101010104010101 0000000000000000 93C9B64042EAA240 +0101010102010101 0000000000000000 5570530829705592 +0101010101800101 0000000000000000 8638809E878787A0 +0101010101400101 0000000000000000 41B9A79AF79AC208 +0101010101200101 0000000000000000 7A9BE42F2009A892 +0101010101100101 0000000000000000 29038D56BA6D2745 +0101010101080101 0000000000000000 5495C6ABF1E5DF51 +0101010101040101 0000000000000000 AE13DBD561488933 +0101010101020101 0000000000000000 024D1FFA8904E389 +0101010101018001 0000000000000000 D1399712F99BF02E +0101010101014001 0000000000000000 14C1D7C1CFFEC79E +0101010101012001 0000000000000000 1DE5279DAE3BED6F +0101010101011001 0000000000000000 E941A33F85501303 +0101010101010801 0000000000000000 DA99DBBC9A03F379 +0101010101010401 0000000000000000 B7FC92F91D8E92E9 +0101010101010201 0000000000000000 AE8E5CAA3CA04E85 +0101010101010180 0000000000000000 9CC62DF43B6EED74 +0101010101010140 0000000000000000 D863DBB5C59A91A0 +0101010101010120 0000000000000000 A1AB2190545B91D7 +0101010101010110 0000000000000000 0875041E64C570F7 +0101010101010108 0000000000000000 5A594528BEBEF1CC +0101010101010104 0000000000000000 FCDB3291DE21F0C0 +0101010101010102 0000000000000000 869EFD7F9F265A09 +1046913489980131 0000000000000000 88D55E54F54C97B4 +1007103489988020 0000000000000000 0C0CC00C83EA48FD +10071034C8980120 0000000000000000 83BC8EF3A6570183 +1046103489988020 0000000000000000 DF725DCAD94EA2E9 +1086911519190101 0000000000000000 E652B53B550BE8B0 +1086911519580101 0000000000000000 AF527120C485CBB0 +5107B01519580101 0000000000000000 0F04CE393DB926D5 +1007B01519190101 0000000000000000 C9F00FFC74079067 +3107915498080101 0000000000000000 7CFD82A593252B4E +3107919498080101 0000000000000000 CB49A2F9E91363E3 +10079115B9080140 0000000000000000 00B588BE70D23F56 +3107911598080140 0000000000000000 406A9A6AB43399AE +1007D01589980101 0000000000000000 6CB773611DCA9ADA +9107911589980101 0000000000000000 67FD21C17DBB5D70 +9107D01589190101 0000000000000000 9592CB4110430787 +1007D01598980120 0000000000000000 A6B7FF68A318DDD3 +1007940498190101 0000000000000000 4D102196C914CA16 +0107910491190401 0000000000000000 2DFA9F4573594965 +0107910491190101 0000000000000000 B46604816C0E0774 +0107940491190401 0000000000000000 6E7E6221A4F34E87 +19079210981A0101 0000000000000000 AA85E74643233199 +1007911998190801 0000000000000000 2E5A19DB4D1962D6 +10079119981A0801 0000000000000000 23A866A809D30894 +1007921098190101 0000000000000000 D812D961F017D320 +100791159819010B 0000000000000000 055605816E58608F +1004801598190101 0000000000000000 ABD88E8B1B7716F1 +1004801598190102 0000000000000000 537AC95BE69DA1E1 +1004801598190108 0000000000000000 AED0F6AE3C25CDD8 +1002911598100104 0000000000000000 B3E35A5EE53E7B8D +1002911598190104 0000000000000000 61C79C71921A2EF8 +1002911598100201 0000000000000000 E2F5728F0995013C +1002911698100101 0000000000000000 1AEAC39A61F0A464 +7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B +0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 +07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A +3849674C2602319E 51454B582DDF440A 7178876E01F19B2A +04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 +0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B +0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 +43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A +07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F +04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 +37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 +1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A +584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 +025816164629B007 480D39006EE762F2 A1F9915541020B56 +49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 +4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC +49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A +018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 +1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 diff --git a/src/lib/crypto/md4/.rconf b/src/lib/crypto/md4/.rconf new file mode 100644 index 0000000..de30fd8 --- /dev/null +++ b/src/lib/crypto/md4/.rconf @@ -0,0 +1,2 @@ +ignore RFC1186.TXT +ignore RFC1186B.TXT diff --git a/src/lib/crypto/md4/RFC1186.TXT b/src/lib/crypto/md4/RFC1186.TXT new file mode 100644 index 0000000..5c0d941 --- /dev/null +++ b/src/lib/crypto/md4/RFC1186.TXT @@ -0,0 +1,1011 @@ + + + + + + +Network Working Group R. Rivest +Request for Comments: 1186 MIT Laboratory for Computer Science + October 1990 + + + The MD4 Message Digest Algorithm + +Status of this Memo + + This RFC is the specification of the MD4 Digest Algorithm. If you + are going to implement MD4, it is suggested you do it this way. This + memo is for informational use and does not constitute a standard. + Distribution of this memo is unlimited. + +Table of Contents + + 1. Abstract .................................................... 1 + 2. Terminology and Notation .................................... 2 + 3. MD4 Algorithm Description ................................... 2 + 4. Extensions .................................................. 6 + 5. Summary ..................................................... 7 + 6. Acknowledgements ............................................ 7 + APPENDIX - Reference Implementation ............................. 7 + Security Considerations.......................................... 18 + Author's Address................................................. 18 + +1. Abstract + + This note describes the MD4 message digest algorithm. The algorithm + takes as input an input message of arbitrary length and produces as + output a 128-bit "fingerprint" or "message digest" of the input. It + is conjectured that it is computationally infeasible to produce two + messages having the same message digest, or to produce any message + having a given prespecified target message digest. The MD4 algorithm + is thus ideal for digital signature applications, where a large file + must be "compressed" in a secure manner before being signed with the + RSA public-key cryptosystem. + + The MD4 algorithm is designed to be quite fast on 32-bit machines. + On a SUN Sparc station, MD4 runs at 1,450,000 bytes/second. On a DEC + MicroVax II, MD4 runs at approximately 70,000 bytes/second. On a + 20MHz 80286, MD4 runs at approximately 32,000 bytes/second. In + addition, the MD4 algorithm does not require any large substitution + tables; the algorithm can be coded quite compactly. + + The MD4 algorithm is being placed in the public domain for review and + possible adoption as a standard. + + + + +Rivest [Page 1] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + (Note: The document supersedes an earlier draft. The algorithm + described here is a slight modification of the one described in the + draft.) + +2. Terminology and Notation + + In this note a "word" is a 32-bit quantity and a byte is an 8-bit + quantity. A sequence of bits can be interpreted in a natural manner + as a sequence of bytes, where each consecutive group of 8 bits is + interpreted as a byte with the high-order (most significant) bit of + each byte listed first. Similarly, a sequence of bytes can be + interpreted as a sequence of 32-bit words, where each consecutive + group of 4 bytes is interpreted as a word with the low-order (least + significant) byte given first. + + Let x_i denote "x sub i". If the subscript is an expression, we + surround it in braces, as in x_{i+1}. Similarly, we use ^ for + superscripts (exponentiation), so that x^i denotes x to the i-th + power. + + Let the symbol "+" denote addition of words (i.e., modulo- 2^32 + addition). Let X <<< s denote the 32-bit value obtained by circularly + shifting (rotating) X left by s bit positions. Let not(X) denote the + bit-wise complement of X, and let X v Y denote the bit-wise OR of X + and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY + denote the bit-wise AND of X and Y. + +3. MD4 Algorithm Description + + We begin by supposing that we have a b-bit message as input, and that + we wish to find its message digest. Here b is an arbitrary + nonnegative integer; b may be zero, it need not be a multiple of 8, + and it may be arbitrarily large. We imagine the bits of the message + written down as follows: + + m_0 m_1 ... m_{b-1} . + + The following five steps are performed to compute the message digest + of the message. + + Step 1. Append padding bits + + The message is "padded" (extended) so that its length (in bits) + is congruent to 448, modulo 512. That is, the message is + extended so that it is just 64 bits shy of being a multiple of + 512 bits long. Padding is always performed, even if the length + of the message is already congruent to 448, modulo 512 (in + which case 512 bits of padding are added). + + + +Rivest [Page 2] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + Padding is performed as follows: a single "1" bit is appended + to the message, and then enough zero bits are appended so that + the length in bits of the padded message becomes congruent to + 448, modulo 512. + + Step 2. Append length + + A 64-bit representation of b (the length of the message before + the padding bits were added) is appended to the result of the + previous step. In the unlikely event that b is greater than + 2^64, then only the low-order 64 bits of b are used. (These + bits are appended as two 32-bit words and appended low-order + word first in accordance with the previous conventions.) + + At this point the resulting message (after padding with bits + and with b) has a length that is an exact multiple of 512 bits. + Equivalently, this message has a length that is an exact + multiple of 16 (32-bit) words. Let M[0 ... N-1] denote the + words of the resulting message, where N is a multiple of 16. + + Step 3. Initialize MD buffer + + A 4-word buffer (A,B,C,D) is used to compute the message + digest. Here each of A,B,C,D are 32-bit registers. These + registers are initialized to the following values in + hexadecimal, low-order bytes first): + + word A: 01 23 45 67 + word B: 89 ab cd ef + word C: fe dc ba 98 + word D: 76 54 32 10 + + Step 4. Process message in 16-word blocks + + We first define three auxiliary functions that each take + as input three 32-bit words and produce as output one + 32-bit word. + + f(X,Y,Z) = XY v not(X)Z + g(X,Y,Z) = XY v XZ v YZ + h(X,Y,Z) = X xor Y xor Z + + In each bit position f acts as a conditional: if x then y else + z. (The function f could have been defined using + instead of + v since XY and not(X)Z will never have 1's in the same bit + position.) In each bit position g acts as a majority function: + if at least two of x, y, z are on, then g has a one in that bit + position, else g has a zero. It is interesting to note that if + + + +Rivest [Page 3] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + the bits of X, Y, and Z are independent and unbiased, the each + bit of f(X,Y,Z) will be independent and unbiased, and similarly + each bit of g(X,Y,Z) will be independent and unbiased. The + function h is the bit-wise "xor" or "parity" function; it has + properties similar to those of f and g. + + Do the following: + + For i = 0 to N/16-1 do /* process each 16-word block */ + For j = 0 to 15 do: /* copy block i into X */ + Set X[j] to M[i*16+j]. + end /* of loop on j */ + Save A as AA, B as BB, C as CC, and D as DD. + + [Round 1] + Let [A B C D i s] denote the operation + A = (A + f(B,C,D) + X[i]) <<< s . + Do the following 16 operations: + [A B C D 0 3] + [D A B C 1 7] + [C D A B 2 11] + [B C D A 3 19] + [A B C D 4 3] + [D A B C 5 7] + [C D A B 6 11] + [B C D A 7 19] + [A B C D 8 3] + [D A B C 9 7] + [C D A B 10 11] + [B C D A 11 19] + [A B C D 12 3] + [D A B C 13 7] + [C D A B 14 11] + [B C D A 15 19] + + [Round 2] + Let [A B C D i s] denote the operation + A = (A + g(B,C,D) + X[i] + 5A827999) <<< s . + (The value 5A..99 is a hexadecimal 32-bit + constant, written with the high-order digit + first. This constant represents the square + root of 2. The octal value of this constant + is 013240474631. See Knuth, The Art of + Programming, Volume 2 (Seminumerical + Algorithms), Second Edition (1981), + Addison-Wesley. Table 2, page 660.) + Do the following 16 operations: + [A B C D 0 3] + + + +Rivest [Page 4] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + [D A B C 4 5] + [C D A B 8 9] + [B C D A 12 13] + [A B C D 1 3] + [D A B C 5 5] + [C D A B 9 9] + [B C D A 13 13] + [A B C D 2 3] + [D A B C 6 5] + [C D A B 10 9] + [B C D A 14 13] + [A B C D 3 3] + [D A B C 7 5] + [C D A B 11 9] + [B C D A 15 13] + + [Round 3] + Let [A B C D i s] denote the operation + A = (A + h(B,C,D) + X[i] + 6ED9EBA1) <<< s . + (The value 6E..A1 is a hexadecimal 32-bit + constant, written with the high-order digit + first. This constant represents the square + root of 3. The octal value of this constant + is 015666365641. See Knuth, The Art of + Programming, Volume 2 (Seminumerical + Algorithms), Second Edition (1981), + Addison-Wesley. Table 2, page 660.) + Do the following 16 operations: + [A B C D 0 3] + [D A B C 8 9] + [C D A B 4 11] + [B C D A 12 15] + [A B C D 2 3] + [D A B C 10 9] + [C D A B 6 11] + [B C D A 14 15] + [A B C D 1 3] + [D A B C 9 9] + [C D A B 5 11] + [B C D A 13 15] + [A B C D 3 3] + [D A B C 11 9] + [C D A B 7 11] + [B C D A 15 15] + + Then perform the following additions: + A = A + AA + B = B + BB + + + +Rivest [Page 5] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + C = C + CC + D = D + DD + (That is, each of the four registers is incremented by + the value it had before this block was started.) + + end /* of loop on i */ + + Step 5. Output + + The message digest produced as output is A,B,C,D. That is, we + begin with the low-order byte of A, and end with the high-order + byte of D. + + This completes the description of MD4. A reference + implementation in C is given in the Appendix. + +4. Extensions + + If more than 128 bits of output are required, then the following + procedure is recommended to obtain a 256-bit output. (There is no + provision made for obtaining more than 256 bits.) + + Two copies of MD4 are run in parallel over the input. The first copy + is standard as described above. The second copy is modified as + follows. + + The initial state of the second copy is: + word A: 00 11 22 33 + word B: 44 55 66 77 + word C: 88 99 aa bb + word D: cc dd ee ff + + The magic constants in rounds 2 and 3 for the second copy of MD4 are + changed from sqrt(2) and sqrt(3) to cuberoot(2) and cuberoot(3): + + Octal Hex + Round 2 constant 012050505746 50a28be6 + Round 3 constant 013423350444 5c4dd124 + + Finally, after every 16-word block is processed (including the last + block), the values of the A registers in the two copies are + exchanged. + + The final message digest is obtaining by appending the result of the + second copy of MD4 to the end of the result of the first copy of MD4. + + + + + + +Rivest [Page 6] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + +5. Summary + + The MD4 message digest algorithm is simple to implement, and provides + a "fingerprint" or message digest of a message of arbitrary length. + + It is conjectured that the difficulty of coming up with two messages + having the same message digest is on the order of 2^64 operations, + and that the difficulty of coming up with any message having a given + message digest is on the order of 2^128 operations. The MD4 + algorithm has been carefully scrutinized for weaknesses. It is, + however, a relatively new algorithm and further security analysis is + of course justified, as is the case with any new proposal of this + sort. The level of security provided by MD4 should be sufficient for + implementing very high security hybrid digital signature schemes + based on MD4 and the RSA public-key cryptosystem. + +6. Acknowledgements + + I'd like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, and + Noam Nisan for numerous helpful comments and suggestions. + +APPENDIX - Reference Implementation + +This appendix contains the following files: + + md4.h -- header file for using MD4 implementation + md4.c -- the source code for MD4 routines + md4driver.c -- a sample "user" routine + session -- sample results of running md4driver + + /* + ** ******************************************************************** + ** md4.h -- Header file for implementation of ** + ** MD4 Message Digest Algorithm ** + ** Updated: 2/13/90 by Ronald L. Rivest ** + ** (C) 1990 RSA Data Security, Inc. ** + ** ******************************************************************** + */ + + /* MDstruct is the data structure for a message digest computation. + */ + typedef struct { + unsigned int buffer[4]; /* Holds 4-word result of MD computation */ + unsigned char count[8]; /* Number of bits processed so far */ + unsigned int done; /* Nonzero means MD computation finished */ + } MDstruct, *MDptr; + + /* MDbegin(MD) + + + +Rivest [Page 7] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + ** Input: MD -- an MDptr + ** Initialize the MDstruct prepatory to doing a message digest + ** computation. + */ + extern void MDbegin(); + + /* MDupdate(MD,X,count) + ** Input: MD -- an MDptr + ** X -- a pointer to an array of unsigned characters. + ** count -- the number of bits of X to use (an unsigned int). + ** Updates MD using the first "count" bits of X. + ** The array pointed to by X is not modified. + ** If count is not a multiple of 8, MDupdate uses high bits of + ** last byte. + ** This is the basic input routine for a user. + ** The routine terminates the MD computation when count < 512, so + ** every MD computation should end with one call to MDupdate with a + ** count less than 512. Zero is OK for a count. + */ + extern void MDupdate(); + + /* MDprint(MD) + ** Input: MD -- an MDptr + ** Prints message digest buffer MD as 32 hexadecimal digits. + ** Order is from low-order byte of buffer[0] to high-order byte + ** of buffer[3]. + ** Each byte is printed with high-order hexadecimal digit first. + */ + extern void MDprint(); + + /* + ** End of md4.h + ****************************(cut)***********************************/ + + /* + ** ******************************************************************** + ** md4.c -- Implementation of MD4 Message Digest Algorithm ** + ** Updated: 2/16/90 by Ronald L. Rivest ** + ** (C) 1990 RSA Data Security, Inc. ** + ** ******************************************************************** + */ + + /* + ** To use MD4: + ** -- Include md4.h in your program + ** -- Declare an MDstruct MD to hold the state of the digest + ** computation. + ** -- Initialize MD using MDbegin(&MD) + + + +Rivest [Page 8] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + ** -- For each full block (64 bytes) X you wish to process, call + ** MDupdate(&MD,X,512) + ** (512 is the number of bits in a full block.) + ** -- For the last block (less than 64 bytes) you wish to process, + ** MDupdate(&MD,X,n) + ** where n is the number of bits in the partial block. A partial + ** block terminates the computation, so every MD computation + ** should terminate by processing a partial block, even if it + ** has n = 0. + ** -- The message digest is available in MD.buffer[0] ... + ** MD.buffer[3]. (Least-significant byte of each word + ** should be output first.) + ** -- You can print out the digest using MDprint(&MD) + */ + + /* Implementation notes: + ** This implementation assumes that ints are 32-bit quantities. + ** If the machine stores the least-significant byte of an int in the + ** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST + ** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST + ** should be set to FALSE. Note that on machines with LOWBYTEFIRST + ** FALSE the routine MDupdate modifies has a side-effect on its input + ** array (the order of bytes in each word are reversed). If this is + ** undesired a call to MDreverse(X) can reverse the bytes of X back + ** into order after each call to MDupdate. + + */ + #define TRUE 1 + #define FALSE 0 + #define LOWBYTEFIRST FALSE + + /* Compile-time includes + */ + #include <stdio.h> + #include "md4.h" + + /* Compile-time declarations of MD4 "magic constants". + */ + #define I0 0x67452301 /* Initial values for MD buffer */ + #define I1 0xefcdab89 + #define I2 0x98badcfe + #define I3 0x10325476 + #define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ + #define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ + /* C2 and C3 are from Knuth, The Art of Programming, Volume 2 + ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. + ** Table 2, page 660. + */ + + + +Rivest [Page 9] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + #define fs1 3 /* round 1 shift amounts */ + #define fs2 7 + #define fs3 11 + #define fs4 19 + #define gs1 3 /* round 2 shift amounts */ + #define gs2 5 + #define gs3 9 + #define gs4 13 + #define hs1 3 /* round 3 shift amounts */ + #define hs2 9 + #define hs3 11 + #define hs4 15 + + /* Compile-time macro declarations for MD4. + ** Note: The "rot" operator uses the variable "tmp". + ** It assumes tmp is declared as unsigned int, so that the >> + ** operator will shift in zeros rather than extending the sign bit. + */ + #define f(X,Y,Z) ((X&Y) | ((~X)&Z)) + #define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z)) + #define h(X,Y,Z) (X^Y^Z) + #define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S))) + #define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s) + #define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s) + #define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s) + + /* MDprint(MDp) + ** Print message digest buffer MDp as 32 hexadecimal digits. + ** Order is from low-order byte of buffer[0] to high-order byte of + ** buffer[3]. + ** Each byte is printed with high-order hexadecimal digit first. + ** This is a user-callable routine. + */ + void + MDprint(MDp) + MDptr MDp; + { int i,j; + for (i=0;i<4;i++) + for (j=0;j<32;j=j+8) + printf("%02x",(MDp->buffer[i]>>j) & 0xFF); + } + + /* MDbegin(MDp) + ** Initialize message digest buffer MDp. + ** This is a user-callable routine. + */ + void + MDbegin(MDp) + + + +Rivest [Page 10] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + MDptr MDp; + { int i; + MDp->buffer[0] = I0; + MDp->buffer[1] = I1; + MDp->buffer[2] = I2; + MDp->buffer[3] = I3; + for (i=0;i<8;i++) MDp->count[i] = 0; + MDp->done = 0; + } + + /* MDreverse(X) + ** Reverse the byte-ordering of every int in X. + ** Assumes X is an array of 16 ints. + ** The macro revx reverses the byte-ordering of the next word of X. + */ + #define revx { t = (*X << 16) | (*X >> 16); \ + *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); } + MDreverse(X) + unsigned int *X; + { register unsigned int t; + revx; revx; revx; revx; revx; revx; revx; revx; + revx; revx; revx; revx; revx; revx; revx; revx; + } + + /* MDblock(MDp,X) + ** Update message digest buffer MDp->buffer using 16-word data block X. + ** Assumes all 16 words of X are full of data. + ** Does not update MDp->count. + ** This routine is not user-callable. + */ + static void + MDblock(MDp,X) + MDptr MDp; + unsigned int *X; + { + register unsigned int tmp, A, B, C, D; + #if LOWBYTEFIRST == FALSE + MDreverse(X); + #endif + A = MDp->buffer[0]; + B = MDp->buffer[1]; + C = MDp->buffer[2]; + D = MDp->buffer[3]; + /* Update the message digest buffer */ + ff(A , B , C , D , 0 , fs1); /* Round 1 */ + ff(D , A , B , C , 1 , fs2); + ff(C , D , A , B , 2 , fs3); + ff(B , C , D , A , 3 , fs4); + + + +Rivest [Page 11] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + ff(A , B , C , D , 4 , fs1); + ff(D , A , B , C , 5 , fs2); + ff(C , D , A , B , 6 , fs3); + ff(B , C , D , A , 7 , fs4); + ff(A , B , C , D , 8 , fs1); + ff(D , A , B , C , 9 , fs2); + ff(C , D , A , B , 10 , fs3); + ff(B , C , D , A , 11 , fs4); + ff(A , B , C , D , 12 , fs1); + ff(D , A , B , C , 13 , fs2); + ff(C , D , A , B , 14 , fs3); + ff(B , C , D , A , 15 , fs4); + gg(A , B , C , D , 0 , gs1); /* Round 2 */ + gg(D , A , B , C , 4 , gs2); + gg(C , D , A , B , 8 , gs3); + gg(B , C , D , A , 12 , gs4); + gg(A , B , C , D , 1 , gs1); + gg(D , A , B , C , 5 , gs2); + gg(C , D , A , B , 9 , gs3); + gg(B , C , D , A , 13 , gs4); + gg(A , B , C , D , 2 , gs1); + gg(D , A , B , C , 6 , gs2); + gg(C , D , A , B , 10 , gs3); + gg(B , C , D , A , 14 , gs4); + gg(A , B , C , D , 3 , gs1); + gg(D , A , B , C , 7 , gs2); + gg(C , D , A , B , 11 , gs3); + gg(B , C , D , A , 15 , gs4); + hh(A , B , C , D , 0 , hs1); /* Round 3 */ + hh(D , A , B , C , 8 , hs2); + hh(C , D , A , B , 4 , hs3); + hh(B , C , D , A , 12 , hs4); + hh(A , B , C , D , 2 , hs1); + hh(D , A , B , C , 10 , hs2); + hh(C , D , A , B , 6 , hs3); + hh(B , C , D , A , 14 , hs4); + hh(A , B , C , D , 1 , hs1); + hh(D , A , B , C , 9 , hs2); + hh(C , D , A , B , 5 , hs3); + hh(B , C , D , A , 13 , hs4); + hh(A , B , C , D , 3 , hs1); + hh(D , A , B , C , 11 , hs2); + hh(C , D , A , B , 7 , hs3); + hh(B , C , D , A , 15 , hs4); + MDp->buffer[0] += A; + MDp->buffer[1] += B; + MDp->buffer[2] += C; + MDp->buffer[3] += D; + + + +Rivest [Page 12] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + } + + /* MDupdate(MDp,X,count) + ** Input: MDp -- an MDptr + ** X -- a pointer to an array of unsigned characters. + ** count -- the number of bits of X to use. + ** (if not a multiple of 8, uses high bits of last byte.) + ** Update MDp using the number of bits of X given by count. + ** This is the basic input routine for an MD4 user. + ** The routine completes the MD computation when count < 512, so + ** every MD computation should end with one call to MDupdate with a + ** count less than 512. A call with count 0 will be ignored if the + ** MD has already been terminated (done != 0), so an extra call with + ** count 0 can be given as a "courtesy close" to force termination + ** if desired. + */ + void + MDupdate(MDp,X,count) + MDptr MDp; + unsigned char *X; + unsigned int count; + { unsigned int i, tmp, bit, byte, mask; + unsigned char XX[64]; + unsigned char *p; + /* return with no error if this is a courtesy close with count + ** zero and MDp->done is true. + */ + if (count == 0 && MDp->done) return; + /* check to see if MD is already done and report error */ + if (MDp->done) + { printf("\nError: MDupdate MD already done."); return; } + /* Add count to MDp->count */ + tmp = count; + p = MDp->count; + while (tmp) + { tmp += *p; + *p++ = tmp; + tmp = tmp >> 8; + } + /* Process data */ + if (count == 512) + { /* Full block of data to handle */ + MDblock(MDp,(unsigned int *)X); + } + else if (count > 512) /* Check for count too large */ + { printf("\nError: MDupdate called with illegal count value %d." + ,count); + return; + + + +Rivest [Page 13] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + } + else /* partial block -- must be last block so finish up */ + { /* Find out how many bytes and residual bits there are */ + byte = count >> 3; + bit = count & 7; + /* Copy X into XX since we need to modify it */ + for (i=0;i<=byte;i++) XX[i] = X[i]; + for (i=byte+1;i<64;i++) XX[i] = 0; + /* Add padding '1' bit and low-order zeros in last byte */ + mask = 1 << (7 - bit); + XX[byte] = (XX[byte] | mask) & ~( mask - 1); + /* If room for bit count, finish up with this block */ + if (byte <= 55) + { for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned int *)XX); + } + else /* need to do two blocks to finish up */ + { MDblock(MDp,(unsigned int *)XX); + for (i=0;i<56;i++) XX[i] = 0; + for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; + MDblock(MDp,(unsigned int *)XX); + } + /* Set flag saying we're done with MD computation */ + MDp->done = 1; + } + } + + /* + ** End of md4.c + ****************************(cut)***********************************/ + + /* + ** ******************************************************************** + ** md4driver.c -- sample routines to test ** + ** MD4 message digest algorithm. ** + ** Updated: 2/16/90 by Ronald L. Rivest ** + ** (C) 1990 RSA Data Security, Inc. ** + ** ******************************************************************** + */ + + #include <stdio.h> + #include "md4.h" + + /* MDtimetrial() + ** A time trial routine, to measure the speed of MD4. + ** Measures speed for 1M blocks = 64M bytes. + */ + MDtimetrial() + + + +Rivest [Page 14] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + { unsigned int X[16]; + MDstruct MD; + int i; + double t; + for (i=0;i<16;i++) X[i] = 0x01234567 + i; + printf + ("MD4 time trial. Processing 1 million 64-character blocks...\n"); + clock(); + MDbegin(&MD); + for (i=0;i<1000000;i++) MDupdate(&MD,X,512); + MDupdate(&MD,X,0); + t = (double) clock(); /* in microseconds */ + MDprint(&MD); printf(" is digest of 64M byte test input.\n"); + printf("Seconds to process test input: %g\n,t/1e6); + printf("Characters processed per second: %ld.\n,(int)(64e12/t)); + } + + /* MDstring(s) + ** Computes the message digest for string s. + ** Prints out message digest, a space, the string (in quotes) and a + ** carriage return. + */ + MDstring(s) + unsigned char *s; + { unsigned int i, len = strlen(s); + MDstruct MD; + MDbegin(&MD); + for (i=0;i+64<=len;i=i+64) MDupdate(&MD,s+i,512); + MDupdate(&MD,s+i,(len-i)*8); + MDprint(&MD); + printf(" \"%s\"\n",s); + } + + /* MDfile(filename) + ** Computes the message digest for a specified file. + ** Prints out message digest, a space, the file name, and a + ** carriage return. + */ + MDfile(filename) + char *filename; + { FILE *f = fopen(filename,"rb"); + unsigned char X[64]; + MDstruct MD; + int b; + if (f == NULL) + { printf("%s can't be opened.\n",filename); return; } + MDbegin(&MD); + while ((b=fread(X,1,64,f))!=0) MDupdate(&MD,X,b*8); + + + +Rivest [Page 15] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + MDupdate(&MD,X,0); + MDprint(&MD); + printf(" %s\n",filename); + fclose(f); + } + + /* MDfilter() + ** Writes the message digest of the data from stdin onto stdout, + ** followed by a carriage return. + */ + MDfilter() + { unsigned char X[64]; + MDstruct MD; + int b; + MDbegin(&MD); + while ((b=fread(X,1,64,stdin))!=0) MDupdate(&MD,X,b*8); + MDupdate(&MD,X,0); + MDprint(&MD); + printf("\n"); + } + + /* MDtestsuite() + ** Run a standard suite of test data. + */ + MDtestsuite() + { + printf("MD4 test suite results:\n"); + MDstring(""); + MDstring("a"); + MDstring("abc"); + MDstring("message digest"); + MDstring("abcdefghijklmnopqrstuvwxyz"); + MDstring + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + MDfile("foo"); /* Contents of file foo are "abc" */ + } + + main(argc,argv) + int argc; + char *argv[]; + { int i; + /* For each command line argument in turn: + ** filename -- prints message digest and name of file + ** -sstring -- prints message digest and contents of string + ** -t -- prints time trial statistics for 64M bytes + ** -x -- execute a standard suite of test data + ** (no args) -- writes messages digest of stdin onto stdout + */ + + + +Rivest [Page 16] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + if (argc==1) MDfilter(); + else + for (i=1;i<argc;i++) + if (argv[i][0]=='-' && argv[i][1]=='s') MDstring(argv[i]+2); + else if (strcmp(argv[i],"-t")==0) MDtimetrial(); + else if (strcmp(argv[i],"-x")==0) MDtestsuite(); + else MDfile(argv[i]); + } + + /* + ** end of md4driver.c + ****************************(cut)***********************************/ + + + -------------------------------------------------------------------- + --- Sample session. Compiling and using MD4 on SUN Sparcstation --- + -------------------------------------------------------------------- + >ls + total 66 + -rw-rw-r-- 1 rivest 3 Feb 14 17:40 abcfile + -rwxrwxr-x 1 rivest 24576 Feb 17 12:28 md4 + -rw-rw-r-- 1 rivest 9347 Feb 17 00:37 md4.c + -rw-rw-r-- 1 rivest 25150 Feb 17 12:25 md4.doc + -rw-rw-r-- 1 rivest 1844 Feb 16 21:21 md4.h + -rw-rw-r-- 1 rivest 3497 Feb 17 12:27 md4driver.c + > + >cc -o md4 -O4 md4.c md4driver.c + md4.c: + md4driver.c: + Linking: + > + >md4 -x + MD4 test suite results: + 31d6cfe0d16ae931b73c59d7e0c089c0 "" + bde52cb31de33e46245e05fbdbd6fb24 "a" + a448017aaf21d8525fc10ae87aa6729d "abc" + d9130a8164549fe818874806e1c7014b "message digest" + d79e1c308aa5bbcdeea8ed63df412da9 "abcdefghijklmnopqrstuvwxyz" + 043f8582f241db351ce627e153e7f0e4 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + a448017aaf21d8525fc10ae87aa6729d abcfile + > + >md4 -sabc -shi + a448017aaf21d8525fc10ae87aa6729d "abc" + cfaee2512bd25eb033236f0cd054e308 "hi" + > + >md4 * + a448017aaf21d8525fc10ae87aa6729d abcfile + + + +Rivest [Page 17] + +RFC 1186 MD4 Message Digest Algorithm October 1990 + + + d316f994da0e951cf9502928a1f73300 md4 + 379adb39eada0dfdbbdfdcd0d9def8c4 md4.c + 9a3f73327c65954198b1f45a3aa12665 md4.doc + 37fe165ac177b461ff78b86d10e4ff33 md4.h + 7dcba2e2dc4d8f1408d08beb17dabb2a md4.o + 08790161bfddc6f5788b4353875cb1c3 md4driver.c + 1f84a7f690b0545d2d0480d5d3c26eea md4driver.o + > + >cat abcfile | md4 + a448017aaf21d8525fc10ae87aa6729d + > + >md4 -t + MD4 time trial. Processing 1 million 64-character blocks... + 6325bf77e5891c7c0d8104b64cc6e9ef is digest of 64M byte test input. + Seconds to process test input: 44.0982 + Characters processed per second: 1451305. + > + > + ------------------------ end of sample session -------------------- + + Note: A version of this document including the C source code is + available for FTP from THEORY.LSC.MIT.EDU in the file "md4.doc". + +Security Considerations + + The level of security discussed in this memo by MD4 is considered to + be sufficient for implementing very high security hybrid digital + signature schemes based on MD4 and the RSA public-key cryptosystem. + +Author's Address + + Ronald L. Rivest + Massachusetts Institute of Technology + Laboratory for Computer Science + NE43-324 + 545 Technology Square + Cambridge, MA 02139-1986 + + Phone: (617) 253-5880 + + EMail: rivest@theory.lcs.mit.edu + + + + + + + + + + +Rivest [Page 18] +
\ No newline at end of file diff --git a/src/lib/crypto/md4/RFC1186B.TXT b/src/lib/crypto/md4/RFC1186B.TXT new file mode 100644 index 0000000..6be1a29 --- /dev/null +++ b/src/lib/crypto/md4/RFC1186B.TXT @@ -0,0 +1,1041 @@ +*** Note: This is a revised version of "md4.doc", obtained as "md4.doc" +*** by anonymous ftp from theory.lcs.mit.edu. The original version is +*** still available as "md4.doc.old". The MD4 algorithm is unchanged, but +*** the newer version of the code is somewhat more portable, although slightly +*** slower. [Ronald L. Rivest 1/13/91] + +Network Working Group R. Rivest +Request for Comments: 1186B MIT Laboratory for Computer Science +Updates: RFC 1186 S. Dusse + RSA Data Security, Inc. + 9 January 1991 + + + + The MD4 Message Digest Algorithm + + +STATUS OF THIS MEMO + + This RFC is the specification of the MD4 Digest Algorithm. If you + are going to implement MD4, it is suggested you do it this way. This + memo is for informational use and does not constitute a standard. + Distribution of this memo is unlimited. + +Table of Contents + + 1. Executive Summary 1 + 2. Terminology and Notation 2 + 3. MD4 Algorithm Description 2 + 4. Extensions 6 + 5. Summary 6 + 6. Acknowledgements 7 + Security Considerations 7 + References 7 + APPENDIX - Reference Implementation 7 + +1. Executive Summary + + This note describes the MD4 message digest algorithm. The algorithm + takes as input an input message of arbitrary length and produces as + output a 128-bit "fingerprint" or "message digest" of the input. It + is conjectured that it is computationally infeasible to produce two + messages having the same message digest, or to produce any message + having a given prespecified target message digest. The MD4 algorithm + is thus ideal for digital signature applications, where a large file + must be "compressed" in a secure manner before being signed with the + RSA public-key cryptosystem. + + The MD4 algorithm is designed to be quite fast on 32-bit machines. + In addition, the MD4 algorithm does not require any large + substitution tables; the algorithm can be coded quite compactly. + + The MD4 algorithm is being placed in the public domain for review and + possible adoption as a standard. + + This RFC is a revision of the October 1990 RFC 1186. The main + difference is that the reference implementation of MD4 in the + appendix is more portable. + + +Rivest [Page 1] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + +2. Terminology and Notation + + In this note a "word" is a 32-bit quantity and a byte is an 8-bit + quantity. A sequence of bits can be interpreted in a natural manner + as a sequence of bytes, where each consecutive group of 8 bits is + interpreted as a byte with the high-order (most significant) bit of + each byte listed first. Similarly, a sequence of bytes can be + interpreted as a sequence of 32-bit words, where each consecutive + group of 4 bytes is interpreted as a word with the low-order (least + significant) byte given first. + + Let x_i denote "x sub i". If the subscript is an expression, we + surround it in braces, as in x_{i+1}. Similarly, we use ^ for + superscripts (exponentiation), so that x^i denotes x to the i-th + power. + + Let the symbol "+" denote addition of words (i.e., modulo- 2^32 + addition). Let X <<< s denote the 32-bit value obtained by + circularly shifting (rotating) X left by s bit positions. Let not(X) + denote the bit-wise complement of X, and let X v Y denote the bit- + wise OR of X and Y. Let X xor Y denote the bit-wise XOR of X and Y, + and let XY denote the bit-wise AND of X and Y. + + +3. MD4 Algorithm Description + + We begin by supposing that we have a b-bit message as input, and that + we wish to find its message digest. Here b is an arbitrary + nonnegative integer; b may be zero, it need not be a multiple of 8, + and it may be arbitrarily large. We imagine the bits of the message + written down as follows: + + m_0 m_1 ... m_{b-1} . + + The following five steps are performed to compute the message digest + of the message. + + +3.1 Step 1. Append padding bits + + The message is "padded" (extended) so that its length (in bits) is + congruent to 448, modulo 512. That is, the message is extended so + that it is just 64 bits shy of being a multiple of 512 bits long. + Padding is always performed, even if the length of the message is + already congruent to 448, modulo 512 (in which case 512 bits of + padding are added). + + Padding is performed as follows: a single "1" bit is appended to the + message, and then enough zero bits are appended so that the length in + bits of the padded message becomes congruent to 448, modulo 512. + + + + +Rivest [Page 2] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + +3.2 Step 2. Append length + + A 64-bit representation of b (the length of the message before the + padding bits were added) is appended to the result of the previous + step. In the unlikely event that b is greater than 2^64, then only + the low-order 64 bits of b are used. (These bits are appended as two + 32-bit words and appended low-order word first in accordance with the + previous conventions.) + + At this point the resulting message (after padding with bits and with + b) has a length that is an exact multiple of 512 bits. Equivalently, + this message has a length that is an exact multiple of 16 (32-bit) + words. Let M[0 ... N-1] denote the words of the resulting message, + where N is a multiple of 16. + + +3.3 Step 3. Initialize MD buffer + + A 4-word buffer (A,B,C,D) is used to compute the message digest. + Here each of A,B,C,D are 32-bit registers. These registers are + initialized to the following values in hexadecimal, low-order bytes + first): + + word A: 01 23 45 67 + word B: 89 ab cd ef + word C: fe dc ba 98 + word D: 76 54 32 10 + + +3.4 Step 4. Process message in 16-word blocks + + We first define three auxiliary functions that each take as input + three 32-bit words and produce as output one 32-bit word. + + f(X,Y,Z) = XY v not(X)Z + g(X,Y,Z) = XY v XZ v YZ + h(X,Y,Z) = X xor Y xor Z + + In each bit position f acts as a conditional: if x then y else z. + (The function f could have been defined using + instead of v since XY + and not(X)Z will never have 1's in the same bit position.) In each + bit position g acts as a majority function: if at least two of x, y, + z are on, then g has a one in that bit position, else g has a zero. + It is interesting to note that if the bits of X, Y, and Z are + independent and unbiased, the each bit of f(X,Y,Z) will be + independent and unbiased, and similarly each bit of g(X,Y,Z) will be + independent and unbiased. The function h is the bit-wise "xor" or + "parity" function; it has properties similar to those of f and g. + + Do the following: + + For i = 0 to N/16-1 do: /* process each 16-word block */ + For j = 0 to 15 do: /* copy block i into X */ + Set X[j] to M[i*16+j]. +Rivest [Page 3] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + end /* of loop on j */ + Save A as AA, B as BB, C as CC, and D as DD. + + [Round 1] + Let [A B C D i s] denote the operation + A = (A + f(B,C,D) + X[i]) <<< s . + + Do the following 16 operations: + [A B C D 0 3] + [D A B C 1 7] + [C D A B 2 11] + [B C D A 3 19] + [A B C D 4 3] + [D A B C 5 7] + [C D A B 6 11] + [B C D A 7 19] + [A B C D 8 3] + [D A B C 9 7] + [C D A B 10 11] + [B C D A 11 19] + [A B C D 12 3] + [D A B C 13 7] + [C D A B 14 11] + [B C D A 15 19] + + [Round 2] + Let [A B C D i s] denote the operation + A = (A + g(B,C,D) + X[i] + 5A827999) <<< s . + + (The value 5A..99 is a hexadecimal 32-bit + constant, written with the high-order digit + first. This constant represents the square + root of 2. The octal value of this constant + is 013240474631. See Knuth, The Art of + Programming, Volume 2 (Seminumerical + Algorithms), Second Edition (1981), + Addison-Wesley. Table 2, page 660.) + + Do the following 16 operations: + [A B C D 0 3] + [D A B C 4 5] + [C D A B 8 9] + [B C D A 12 13] + [A B C D 1 3] + [D A B C 5 5] + [C D A B 9 9] + [B C D A 13 13] + [A B C D 2 3] + [D A B C 6 5] + [C D A B 10 9] + [B C D A 14 13] + [A B C D 3 3] + [D A B C 7 5] + [C D A B 11 9] +Rivest [Page 4] [B C D A 15 13] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + + [Round 3] + Let [A B C D i s] denote the operation + A = (A + h(B,C,D) + X[i] + 6ED9EBA1) <<< s . + + (The value 6E..A1 is a hexadecimal 32-bit + constant, written with the high-order digit + first. This constant represents the square + root of 3. The octal value of this constant + is 015666365641. See Knuth, The Art of + Programming, Volume 2 (Seminumerical + Algorithms), Second Edition (1981), + Addison-Wesley. Table 2, page 660.) + + Do the following 16 operations: + [A B C D 0 3] + [D A B C 8 9] + [C D A B 4 11] + [B C D A 12 15] + [A B C D 2 3] + [D A B C 10 9] + [C D A B 6 11] + [B C D A 14 15] + [A B C D 1 3] + [D A B C 9 9] + [C D A B 5 11] + [B C D A 13 15] + [A B C D 3 3] + [D A B C 11 9] + [C D A B 7 11] + [B C D A 15 15] + + Then perform the following additions: + A = A + AA + B = B + BB + C = C + CC + D = D + DD + + (That is, each of the four registers is + incremented by the value it had before + this block was started.) + + end /* of loop on i */ + + +3.5 Step 5. Output + + The message digest produced as output is A,B,C,D. That is, we begin + with the low-order byte of A, and end with the high-order byte of D. + + This completes the description of MD4. A reference implementation in + C is given in the Appendix. + + +Rivest [Page 5] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + +4. Extensions + + If more than 128 bits of output are required, then the following + procedure is recommended to obtain a 256-bit output. (There is no + provision made for obtaining more than 256 bits.) + + Two copies of MD4 are run in parallel over the input. The first copy + is standard as described above. The second copy is modified as + follows. + + The initial state of the second copy is: + + word A: 00 11 22 33 + word B: 44 55 66 77 + word C: 88 99 aa bb + word D: cc dd ee ff + + The magic constants in rounds 2 and 3 for the second copy of MD4 are + changed from sqrt(2) and sqrt(3) to cuberoot(2) and cuberoot(3): + + Octal Hex + Round 2 constant 012050505746 50a28be6 + Round 3 constant 013423350444 5c4dd124 + + Finally, after every 16-word block is processed (including the last + block), the values of the A registers in the two copies are + exchanged. + + The final message digest is obtaining by appending the result of the + second copy of MD4 to the end of the result of the first copy of MD4. + + +5. Summary + + The MD4 message digest algorithm is simple to implement, and provides + a "fingerprint" or message digest of a message of arbitrary length. + It is conjectured that the difficulty of coming up with two messages + having the same message digest is on the order of 2^64 operations, + and that the difficulty of coming up with any message having a given + message digest is on the order of 2^128 operations. The MD4 + algorithm has been carefully scrutinized for weaknesses. It is, + however, a relatively new algorithm and further security analysis is + of course justified, as is the case with any new proposal of this + sort. The level of security provided by MD4 should be sufficient for + implementing very high security hybrid digital signature schemes + based on MD4 and the RSA public-key cryptosystem. + + +6. Acknowledgements + + We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, + and Noam Nisan for numerous helpful comments and suggestions. + + +Rivest [Page 6] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + +Security Considerations + + The level of security discussed in this memo by MD4 is considered to + be sufficient for implementing very high security hybrid digital + signature schemes based on MD4 and the RSA public-key cryptosystem. + + +Authors' Addresses + + Ronald L. Rivest + Massachusetts Institute of Technology + Laboratory for Computer Science + NE43-324 + 545 Technology Square + Cambridge, MA 02139-1986 + Phone: (617) 253-5880 + EMail: rivest@theory.lcs.mit.edu + + Steve Dusse + RSA Data Security, Inc. + 10 Twin Dolphin Dr. + Redwood City, CA 94065 + Phone: (415) 595-8782 + EMail: dusse@rsa.com + + +References + + [1] Rivest, R.L. The MD4 message digest algorithm. Presented at + CRYPTO '90 (Santa Barbara, CA, August 11-15, 1990). + + +APPENDIX - Reference Implementation + + This appendix contains the following files: + + md4.h -- header file for using MD4 implementation + + md4.c -- the source code for MD4 routines + + md4driver.c -- a sample "user" routine + + session -- sample results of running md4driver + + The implementation of MD4 given in this appendix differs from the one + given in [1] and again in RFC 1186. The main difference is that this + version should compile and run correctly on more platforms than the + other ones. We have sacrificed performance for portability. MD4 + speeds given in [1] and RFC 1186 are not necessarily the same as + those one might obtain with this reference implementation. However, + it is not difficult to improve this implementation on particular + platforms, an exercise left to the reader. Following are some + suggestions: + +Rivest [Page 7] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + 1. Change MD4Block so that the context is not used at all if + it is empty (mdi == 0) and 64 or more bytes remain (inLen + >= 64). In other words, call Transform with inBuf in this + case. (This requires that byte ordering is correct in + inBuf.) + + 2. Implement a procedure MD4BlockLong modeled after MD4Block + where inBuf is UINT4 * instead of unsigned char *. + MD4BlockLong would call Transform directly with 16 word + blocks from inBuf. Call this instead of MD4Block in + general. This works well if you have an I/O procedure that + can read long words from a file. + + 3. On "little-endian" platforms where the lowest-address byte + in a long word is the least significant (and there are no + alignment restrictions), change MD4Block to call Transform + directly with 64-byte blocks from inBuf (casted to a UINT4 + *). + +/* + ********************************************************************** + ** md4.h -- Header file for implementation of MD4 ** + ** RSA Data Security, Inc. MD4 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD4 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD4 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +/* typedef a 32 bit type */ +typedef unsigned long int UINT4; +Rivest [Page 8] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + +/* Data structure for MD4 (Message Digest) computation */ +typedef struct { + UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD4Final call */ +} MD4_CTX; + +void MD4Init (); +void MD4Update (); +void MD4Final (); + +/* + ********************************************************************** + ** End of md4.h ** + ******************************* (cut) ******************************** + */ + +/* + ********************************************************************** + ** md4.c ** + ** RSA Data Security, Inc. MD4 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD4 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD4 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#include "md4.h" + +Rivest [Page 9] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + +/* forward declaration */ +static void Transform (); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) \ + {(a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s));} +#define GG(a, b, c, d, x, s) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)013240474631; \ + (a) = ROTATE_LEFT ((a), (s));} +#define HH(a, b, c, d, x, s) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)015666365641; \ + (a) = ROTATE_LEFT ((a), (s));} + +void MD4Init (mdContext) +MD4_CTX *mdContext; +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +void MD4Update (mdContext, inBuf, inLen) +MD4_CTX *mdContext; +unsigned char *inBuf; +unsigned int inLen; +{ + UINT4 in[16]; + int mdi; +Rivest [Page 10] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void MD4Final (mdContext) +MD4_CTX *mdContext; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD4Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); +Rivest [Page 11] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } +} + +/* Basic MD4 step. Transform buf based on in. + */ +static void Transform (buf, in) +UINT4 *buf; +UINT4 *in; +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + FF (a, b, c, d, in[ 0], 3); + FF (d, a, b, c, in[ 1], 7); + FF (c, d, a, b, in[ 2], 11); + FF (b, c, d, a, in[ 3], 19); + FF (a, b, c, d, in[ 4], 3); + FF (d, a, b, c, in[ 5], 7); + FF (c, d, a, b, in[ 6], 11); + FF (b, c, d, a, in[ 7], 19); + FF (a, b, c, d, in[ 8], 3); + FF (d, a, b, c, in[ 9], 7); + FF (c, d, a, b, in[10], 11); + FF (b, c, d, a, in[11], 19); + FF (a, b, c, d, in[12], 3); + FF (d, a, b, c, in[13], 7); + FF (c, d, a, b, in[14], 11); + FF (b, c, d, a, in[15], 19); + + /* Round 2 */ + GG (a, b, c, d, in[ 0], 3); + GG (d, a, b, c, in[ 4], 5); + GG (c, d, a, b, in[ 8], 9); + GG (b, c, d, a, in[12], 13); + GG (a, b, c, d, in[ 1], 3); + GG (d, a, b, c, in[ 5], 5); + GG (c, d, a, b, in[ 9], 9); + GG (b, c, d, a, in[13], 13); + GG (a, b, c, d, in[ 2], 3); + GG (d, a, b, c, in[ 6], 5); + GG (c, d, a, b, in[10], 9); + GG (b, c, d, a, in[14], 13); + GG (a, b, c, d, in[ 3], 3); + GG (d, a, b, c, in[ 7], 5); +Rivest [Page 12] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + GG (c, d, a, b, in[11], 9); + GG (b, c, d, a, in[15], 13); + + /* Round 3 */ + HH (a, b, c, d, in[ 0], 3); + HH (d, a, b, c, in[ 8], 9); + HH (c, d, a, b, in[ 4], 11); + HH (b, c, d, a, in[12], 15); + HH (a, b, c, d, in[ 2], 3); + HH (d, a, b, c, in[10], 9); + HH (c, d, a, b, in[ 6], 11); + HH (b, c, d, a, in[14], 15); + HH (a, b, c, d, in[ 1], 3); + HH (d, a, b, c, in[ 9], 9); + HH (c, d, a, b, in[ 5], 11); + HH (b, c, d, a, in[13], 15); + HH (a, b, c, d, in[ 3], 3); + HH (d, a, b, c, in[11], 9); + HH (c, d, a, b, in[ 7], 11); + HH (b, c, d, a, in[15], 15); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + ********************************************************************** + ** End of md4.c ** + ******************************* (cut) ******************************** + */ + +/* + ********************************************************************** + ** md4driver.c -- sample routines to test ** + ** RSA Data Security, Inc. MD4 message digest algorithm. ** + ** Created: 2/16/90 RLR ** + ** Updated: 1/91 SRD ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** +Rivest [Page 13] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + */ + +#include <stdio.h> +#include <sys/types.h> +#include <time.h> +#include <string.h> +#include "md4.h" + +/* Prints message digest buffer in mdContext as 32 hexadecimal digits. + Order is from low-order byte to high-order byte of digest. + Each byte is printed with high-order hexadecimal digit first. + */ +static void MDPrint (mdContext) +MD4_CTX *mdContext; +{ + int i; + + for (i = 0; i < 16; i++) + printf ("%02x", mdContext->digest[i]); +} + +/* size of test block */ +#define TEST_BLOCK_SIZE 1000 + +/* number of blocks to process */ +#define TEST_BLOCKS 2000 + +/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */ +static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS; + +/* A time trial routine, to measure the speed of MD4. + Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE + characters. + */ +static void MDTimeTrial () +{ + MD4_CTX mdContext; + time_t endTime, startTime; + unsigned char data[TEST_BLOCK_SIZE]; + unsigned int i; + + /* initialize test data */ + for (i = 0; i < TEST_BLOCK_SIZE; i++) + data[i] = (unsigned char)(i & 0xFF); + + /* start timer */ + printf ("MD4 time trial. Processing %ld characters...\n", TEST_BYTES); + time (&startTime); + + /* digest data in TEST_BLOCK_SIZE byte blocks */ + MD4Init (&mdContext); + for (i = TEST_BLOCKS; i > 0; i--) + MD4Update (&mdContext, data, TEST_BLOCK_SIZE); + MD4Final (&mdContext); +Rivest [Page 14] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + + /* stop timer, get time difference */ + time (&endTime); + MDPrint (&mdContext); + printf (" is digest of test input.\n"); + printf + ("Seconds to process test input: %ld\n", (long)(endTime-startTime)); + printf + ("Characters processed per second: %ld\n", + TEST_BYTES/(endTime-startTime)); +} + +/* Computes the message digest for string inString. + Prints out message digest, a space, the string (in quotes) and a + carriage return. + */ +static void MDString (inString) +char *inString; +{ + MD4_CTX mdContext; + unsigned int len = strlen (inString); + + MD4Init (&mdContext); + MD4Update (&mdContext, inString, len); + MD4Final (&mdContext); + MDPrint (&mdContext); + printf (" \"%s\"\n\n", inString); +} + +/* Computes the message digest for a specified file. + Prints out message digest, a space, the file name, and a carriage + return. + */ +static void MDFile (filename) +char *filename; +{ + FILE *inFile = fopen (filename, "rb"); + MD4_CTX mdContext; + int bytes; + unsigned char data[1024]; + + if (inFile == NULL) { + printf ("%s can't be opened.\n", filename); + return; + } + + MD4Init (&mdContext); + while ((bytes = fread (data, 1, 1024, inFile)) != 0) + MD4Update (&mdContext, data, bytes); + MD4Final (&mdContext); + MDPrint (&mdContext); + printf (" %s\n", filename); + fclose (inFile); +} +Rivest [Page 15] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + +/* Writes the message digest of the data from stdin onto stdout, + followed by a carriage return. + */ +static void MDFilter () +{ + MD4_CTX mdContext; + int bytes; + unsigned char data[16]; + + MD4Init (&mdContext); + while ((bytes = fread (data, 1, 16, stdin)) != 0) + MD4Update (&mdContext, data, bytes); + MD4Final (&mdContext); + MDPrint (&mdContext); + printf ("\n"); +} + +/* Runs a standard suite of test data. + */ +static void MDTestSuite () +{ + printf ("MD4 test suite results:\n\n"); + MDString (""); + MDString ("a"); + MDString ("abc"); + MDString ("message digest"); + MDString ("abcdefghijklmnopqrstuvwxyz"); + MDString + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + MDString + ("1234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890"); + /* Contents of file foo are "abc" */ + MDFile ("foo"); +} + +void main (argc, argv) +int argc; +char *argv[]; +{ + int i; + + /* For each command line argument in turn: + ** filename -- prints message digest and name of file + ** -sstring -- prints message digest and contents of string + ** -t -- prints time trial statistics for 1M characters + ** -x -- execute a standard suite of test data + ** (no args) -- writes messages digest of stdin onto stdout + */ + if (argc == 1) + MDFilter (); + else + for (i = 1; i < argc; i++) +Rivest [Page 16] + + +RFC 1186B The MD4 Message Digest Algorithm 9 January 1991 + + + + if (argv[i][0] == '-' && argv[i][1] == 's') + MDString (argv[i] + 2); + else if (strcmp (argv[i], "-t") == 0) + MDTimeTrial (); + else if (strcmp (argv[i], "-x") == 0) + MDTestSuite (); + else MDFile (argv[i]); +} + +/* + ********************************************************************** + ** End of md4driver.c ** + ******************************* (cut) ******************************** + */ + +----------------------------------------------------------------------- +-- Sample session output obtained by running md4driver test suite -- +----------------------------------------------------------------------- + + MD4 test suite results: + + 31d6cfe0d16ae931b73c59d7e0c089c0 "" + + bde52cb31de33e46245e05fbdbd6fb24 "a" + + a448017aaf21d8525fc10ae87aa6729d "abc" + + d9130a8164549fe818874806e1c7014b "message digest" + + d79e1c308aa5bbcdeea8ed63df412da9 "abcdefghijklmnopqrstuvwxyz" + + 043f8582f241db351ce627e153e7f0e4 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij + klmnopqrstuvwxyz0123456789" + + e33b4ddc9c38f2199c3e7b164fcc0536 "123456789012345678901234567890123456 + 78901234567890123456789012345678901234567890" + + a448017aaf21d8525fc10ae87aa6729d foo + + +----------------------------------------------------------------------- +-- End of sample session -- +-------------------------------- (cut) -------------------------------- + + + Note: A version of this document including the C source code is + available for FTP from RSA.COM in the file "md4.doc". + + + + + + + +Rivest [Page 17] + + + + diff --git a/src/lib/exports.crypto b/src/lib/exports.crypto new file mode 100644 index 0000000..6f70f18 --- /dev/null +++ b/src/lib/exports.crypto @@ -0,0 +1,29 @@ +mit_des_cbc_cksum +mit_des_ecb_encrypt +mit_des_cbc_checksum +mit_des_cryptosystem_entry +mit_des_cbc_cksumtable_entry +krb5_des_cst_entry +mit_des_cbc_encrypt +mit_des_encrypt_func +mit_des_decrypt_func +mit_des_finish_key +mit_des_finish_random_key +mit_des_init_random_key +mit_des_process_key +mit_des_random_key +mit_des_string_to_key +mit_des_fixup_key_parity +mit_des_check_key_parity +mit_des_key_sched +mit_des_new_random_key +mit_des_init_random_number_generator +mit_des_set_random_generator_seed +mit_des_set_sequence_number +mit_des_generate_random_block +mit_des_is_weak_key +rsa_md4_cksumtable_entry +rsa_md4_des_cksumtable_entry +rsa_md5_cksumtable_entry +rsa_md5_des_cksumtable_entry +crc32_cksumtable_entry diff --git a/src/lib/exports.des425 b/src/lib/exports.des425 new file mode 100644 index 0000000..b1d93d1 --- /dev/null +++ b/src/lib/exports.des425 @@ -0,0 +1,17 @@ +des_cbc_cksum +des_ecb_encrypt +des_cbc_encrypt +des_fixup_key_parity +des_check_key_parity +des_key_sched +des_new_random_key +des_init_random_number_generator +des_set_random_generator_seed +des_set_sequence_number +des_generate_random_block +des_pcbc_encrypt +des_quad_cksum +des_random_key +des_read_password +des_string_to_key +des_is_weak_key diff --git a/src/lib/exports.kdb5 b/src/lib/exports.kdb5 new file mode 100644 index 0000000..22d0e6e --- /dev/null +++ b/src/lib/exports.kdb5 @@ -0,0 +1,26 @@ +krb5_kdb_encrypt_key +krb5_kdb_decrypt_key +krb5_db_init +krb5_db_fini +krb5_db_open_database +krb5_db_close_database +krb5_db_set_name +krb5_db_get_age +krb5_db_lock +krb5_db_unlock +krb5_db_create +kdb5_db_destroy +krb5_db_rename +krb5_db_get_principal +krb5_db_free_principal +krb5_db_put_principal +krb5_db_delete_principal +krb5_db_iterate +krb5_db_set_lockmode +krb5_db_verify_master_key +krb5_mkey_pwd_prompt1 +krb5_mkey_pwd_prompt2 +krb5_db_fetch_mkey +krb5_db_setup_mkey_name +krb5_db_store_mkey + diff --git a/src/lib/exports.krb5 b/src/lib/exports.krb5 new file mode 100644 index 0000000..baea62b --- /dev/null +++ b/src/lib/exports.krb5 @@ -0,0 +1,312 @@ +krb5_cc_register +krb5_cc_resolve +krb5_cc_default +krb5_cc_dfl_ops +krb5_config_file +krb5_trans_file +krb5_defkeyname +krb5_lname_file +krb5_max_dgram_size +krb5_max_skdc_timeout +krb5_skdc_timeout_shift +krb5_skdc_timeout_1 +krb5_kdc_udp_portname +krb5_default_pwd_prompt1 +krb5_default_pwd_prompt2 +krb5_init_ets +krb5_ticket2KRB5_Ticket +krb5_tgs_rep2KRB5_KDC__REP +krb5_kdc_req2KRB5_KDC__REQ__BODY +krb5_kdc_req2KRB5_KDC__REQ +krb5_transited2KRB5_TransitedEncoding +krb5_safe2KRB5_KRB__SAFE +krb5_priv2KRB5_KRB__PRIV +krb5_principal2KRB5_PrincipalName +krb5_priv_enc_part2KRB5_EncKrbPrivPart +krb5_pa_data2KRB5_PA__DATA +krb5_last_req2KRB5_LastReq +krb5_keyblock2KRB5_EncryptionKey +krb5_kdc_rep2KRB5_KDC__REP +krb5_enc_tkt_part2KRB5_EncTicketPart +krb5_error2KRB5_KRB__ERROR +krb5_enc_kdc_rep_part2KRB5_EncKDCRepPart +krb5_enc_data2KRB5_EncryptedData +krb5_checksum2KRB5_Checksum +krb5_authenticator2KRB5_Authenticator +krb5_ap_rep_enc_part2KRB5_EncAPRepPart +krb5_ap_req2KRB5_AP__REQ +krb5_ap_rep2KRB5_AP__REP +krb5_addr2KRB5_HostAddress +krb5_address2KRB5_HostAddresses +krb5_authdata2KRB5_AuthorizationData +krb5_flags2KRB5_TicketFlags +krb5_decode_generic +krb5_encode_generic +krb5_fcc_close_file +krb5_fcc_open_file +krb5_fcc_interpret +krb5_cc_file_ops +krb5_fcc_set_flags +krb5_fcc_write +krb5_fcc_store_principal +krb5_fcc_store_addrs +krb5_fcc_store_keyblock +krb5_fcc_store_addr +krb5_fcc_store_data +krb5_fcc_store_int32 +krb5_fcc_store_ui_2 +krb5_fcc_store_keytype +krb5_fcc_store_int +krb5_fcc_store_bool +krb5_fcc_store_times +krb5_fcc_store_flags +krb5_fcc_store_authdata +krb5_fcc_store_authdatum +krb5_fcc_ops +krb5_fcc_skip_principal +krb5_fcc_store +krb5_fcc_start_seq_get +krb5_fcc_retrieve +krb5_fcc_resolve +krb5_fcc_read +krb5_fcc_read_principal +krb5_fcc_read_addrs +krb5_fcc_read_keyblock +krb5_fcc_read_data +krb5_fcc_read_addr +krb5_fcc_read_int32 +krb5_fcc_read_ui_2 +krb5_fcc_read_keytype +krb5_fcc_read_int +krb5_fcc_read_bool +krb5_fcc_read_times +krb5_fcc_read_flags +krb5_fcc_read_authdata +krb5_fcc_read_authdatum +krb5_fcc_next_cred +krb5_fcc_initialize +krb5_fcc_get_principal +krb5_fcc_get_name +krb5_fcc_generate_new +krb5_fcc_end_seq_get +krb5_fcc_destroy +krb5_fcc_close +krb5_scc_interpret +krb5_cc_stdio_ops +krb5_scc_set_flags +krb5_scc_write +krb5_scc_store_principal +krb5_scc_store_addrs +krb5_scc_store_keyblock +krb5_scc_store_addr +krb5_scc_store_data +krb5_scc_store_int32 +krb5_scc_store_ui_2 +krb5_scc_store_keytype +krb5_scc_store_int +krb5_scc_store_bool +krb5_scc_store_times +krb5_scc_store_flags +krb5_scc_store_authdata +krb5_scc_store_authdatum +krb5_scc_ops +krb5_scc_skip_principal +krb5_scc_store +krb5_scc_start_seq_get +krb5_scc_retrieve +krb5_scc_resolve +krb5_scc_read +krb5_scc_read_principal +krb5_scc_read_addrs +krb5_scc_read_keyblock +krb5_scc_read_data +krb5_scc_read_addr +krb5_scc_read_int32 +krb5_scc_read_ui_2 +krb5_scc_read_keytype +krb5_scc_read_int +krb5_scc_read_bool +krb5_scc_read_times +krb5_scc_read_flags +krb5_scc_read_authdata +krb5_scc_read_authdatum +krb5_scc_next_cred +krb5_scc_initialize +krb5_scc_get_principal +krb5_scc_get_name +krb5_scc_generate_new +krb5_scc_end_seq_get +krb5_scc_destroy +krb5_scc_close +krb5_kt_dfl_ops +krb5_ktfile_wresolve +krb5_ktf_writable_ops +krb5_ktf_ops +krb5_ktfileint_openr +krb5_ktfileint_openw +krb5_ktfileint_close +krb5_ktfileint_read_entry +krb5_ktfileint_write_entry +krb5_ktfile_start_seq_get +krb5_ktfile_remove +krb5_ktfile_resolve +krb5_ktfile_get_next +krb5_ktfile_get_name +krb5_ktfile_get_entry +krb5_ktfile_end_get +krb5_ktfile_close +krb5_ktfile_add +krb5_kt_read_service_key +krb5_kt_remove_entry +krb5_kt_free_entry +krb5_kt_default +krb5_kt_register +krb5_kt_resolve +krb5_kt_add_entry +krb5_walk_realm_tree +krb5_unparse_name_ext +krb5_unparse_name +krb5_tgtname +krb5_get_server_rcache +krb5_send_tgs +krb5_sendauth +krb5_recvauth +krb5_rd_safe +krb5_rd_req_decoded +krb5_rd_req_simple +krb5_rd_req +krb5_rd_rep +krb5_rd_priv +krb5_rd_error +krb5_principal_compare +krb5_principal2salt +krb5_parse_name +krb5_mk_safe +krb5_mk_req_extended +krb5_mk_req +krb5_mk_rep +krb5_mk_priv +krb5_mk_error +krb5_clockskew +krb5_kdc_req_sumtype +krb5_kdc_default_options +krb5_kdc_rep_decrypt_proc +krb5_get_in_tkt_with_skey +krb5_get_in_tkt_with_password +krb5_get_in_tkt +krb5_get_credentials +krb5_generate_subkey +krb5_generate_seq_number +krb5_get_cred_via_2tgt +krb5_get_cred_via_tgt +krb5_get_cred_from_kdc +krb5_fulladdr_order +krb5_free_realm_tree +krb5_encrypt_tkt_part +krb5_encode_kdc_rep +krb5_decrypt_tkt_part +krb5_decode_kdc_rep +krb5_copy_keyblock_contents +krb5_copy_ticket +krb5_copy_principal +krb5_copy_keyblock +krb5_copy_data +krb5_copy_creds +krb5_copy_checksum +krb5_copy_authenticator +krb5_copy_authdata +krb5_copy_addresses +krb5_build_principal_va +krb5_build_principal +krb5_build_principal_ext +krb5_address_search +krb5_address_order +krb5_address_compare +krb5_auth_to_rep +krb5_rc_dfl_ops +krb5_rc_io_creat +krb5_rc_io_open +krb5_rc_io_move +krb5_rc_io_write +krb5_rc_io_read +krb5_rc_io_close +krb5_rc_io_destroy +krb5_rc_io_mark +krb5_rc_io_unmark +krb5_rc_dfl_get_name +krb5_rc_dfl_get_span +krb5_rc_dfl_init +krb5_rc_dfl_close +krb5_rc_dfl_destroy +krb5_rc_dfl_resolve +krb5_rc_dfl_recover +krb5_rc_dfl_store +krb5_rc_dfl_expunge +krb5_rc_register_type +krb5_rc_resolve_type +krb5_rc_get_type +krb5_rc_default_type +krb5_rc_default_name +krb5_rc_default +krb5_rc_resolve_full +krb5_free_tkt_authent +krb5_free_tgt_creds +krb5_free_tickets +krb5_free_ticket +krb5_free_safe +krb5_free_priv_enc_part +krb5_free_priv +krb5_free_principal +krb5_free_pa_data +krb5_free_last_req +krb5_free_keyblock +krb5_free_kdc_req +krb5_free_kdc_rep +krb5_free_error +krb5_free_enc_tkt_part +krb5_free_enc_kdc_rep_part +krb5_free_cred_contents +krb5_free_creds +krb5_free_checksum +krb5_free_authenticator +krb5_free_authdata +krb5_free_ap_rep_enc_part +krb5_free_ap_req +krb5_free_ap_rep +krb5_free_addresses +krb5_free_address +krb5_write_message +krb5_us_timeofday +krb5_unlock_file +krb5_timeofday +krb5_sname_to_principal +krb5_sendto_kdc +krb5_read_password +krb5_read_message +krb5_random_confounder +krb5_unpack_full_ipaddr +krb5_net_write +krb5_net_read +krb5_lock_file +krb5_locate_kdc +krb5_os_localaddr +krb5_kuserok +krb5_kt_default_name +krb5_get_host_realm +krb5_gen_replay_name +krb5_gen_portaddr +krb5_get_krbhst +krb5_make_full_ipaddr +krb5_free_host_realm +krb5_free_krbhst +krb5_cc_default_name +krb5_get_default_realm +krb5_aname_to_localname +krb5_csarray +krb5_max_cryptosystem +krb5_keytype_array +krb5_max_keytype +krb5_cksumarray +krb5_max_cksum +krb5_scc_close_file +krb5_scc_open_file diff --git a/src/lib/glue4.c b/src/lib/glue4.c new file mode 100644 index 0000000..08566f0 --- /dev/null +++ b/src/lib/glue4.c @@ -0,0 +1,19 @@ +#include <krb5/krb5.h> + +krb5_data string_list[3] = { +{11, "FOO.MIT.EDU"}, +{6, "jtkohl"}, +}; + +krb5_data *princ[] = {&string_list[0], &string_list[1], 0}; + +krb5_data string_list2[3] = { +{11, "FOO.MIT.EDU"}, +{4, "rcmd"}, +{13, "lycus.mit.edu"}, +}; + +krb5_data *princ2[] = {&string_list2[0], &string_list2[1], &string_list2[2], 0}; + +krb5_last_req_entry lrentries[] = { {32000, 1}, {0, 3}, {10, 2} }; +krb5_last_req_entry *lrfoo1[] = {&lrentries[0], &lrentries[1], &lrentries[2], 0}; diff --git a/src/lib/gssapi/README b/src/lib/gssapi/README new file mode 100644 index 0000000..dd1a074 --- /dev/null +++ b/src/lib/gssapi/README @@ -0,0 +1,8 @@ +WARNING! The contents of this directory are Alpha-test quality at +best. The definition of the GSS API is still in flux, and this code +has not really been tested due to a lack of an implementation to link +against. + +Look in doc/gss/* for more information. + + diff --git a/src/lib/gssapi/sample/Imakefile b/src/lib/gssapi/sample/Imakefile new file mode 100644 index 0000000..045f87e --- /dev/null +++ b/src/lib/gssapi/sample/Imakefile @@ -0,0 +1,59 @@ +# $Source$ +# $Author$ +# $Id$ +# +# Copyright 1991 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# For copying and distribution information, please see the file +# <krb5/copyright.h>. +# + + DEPLIBS = ../libgssapi.a $(DEPKLIB) +LOCAL_LIBRARIES = ../libgssapi.a $(KLIB) + DEFINES = -DDEBUG + +SRCS = flogin.c fcmd.c flogind.c fsh.c fcp.c login.c logutil.c +OBJS = flogin.o fcmd.o flogind.o fsh.o fcp.o login.o logutil.o + +FLOGINSRCS = flogin.c fcmd.c +FLOGINOBJS = flogin.o fcmd.o + +LOGINSRCS = login.c logutil.c +LOGINOBJS = login.o logutil.o + +FLOGINDSRCS = flogind.c logutil.c +FLOGINDOBJS = flogind.o logutil.o + +FSHSRCS = fsh.c fcmd.c +FSHOBJS = fsh.o fcmd.o + +FSHDSRCS = fshd.c +FSHDOBJS = fshd.o + +FCPSRCS = fcp.c fcmd.c +FCPOBJS = fcp.o fcmd.o + +all:: flogin login.gssapi flogind + +NormalProgramTarget(flogin,$(FLOGINOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) +NormalProgramTarget(login.gssapi,$(LOGINOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) +NormalProgramTarget(flogind,$(FLOGINDOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) +NormalProgramTarget(fsh,$(FSHOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) +NormalProgramTarget(fshd,$(FSHDOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) +NormalProgramTarget(fcp,$(FCPOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),) + +SaberProgramTarget(flogin, $(FLOGINSRCS), $(FLOGINOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) +SaberProgramTarget(login.gssapi, $(LOGINSRCS), $(LOGINOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) +SaberProgramTarget(flogind, $(FLOGINDSRCS), $(FLOGINDOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) +SaberProgramTarget(fsh, $(FSHSRCS), $(FSHOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) +SaberProgramTarget(fshd, $(FSHDSRCS), $(FSHDOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) +SaberProgramTarget(fcp, $(FCPSRCS), $(FCPOBJS), + $(DEPLIBS) $(LOCAL_LIBRARIES),) + +DependTarget() diff --git a/src/lib/gssapi/sample/MAIL.KANNAN b/src/lib/gssapi/sample/MAIL.KANNAN new file mode 100644 index 0000000..0bd0f0a --- /dev/null +++ b/src/lib/gssapi/sample/MAIL.KANNAN @@ -0,0 +1,114 @@ +Received: by E40-PO.MIT.EDU (5.45/4.7) id AA17675; Fri, 24 May 91 14:58:47 EDT +Received: from uucp-gw-1.pa.dec.com by ATHENA.MIT.EDU with SMTP + id AA18573; Fri, 24 May 91 14:58:33 EDT +Received: by uucp-gw-1.pa.dec.com; id AA01785; Fri, 24 May 91 11:56:31 -0700 +Received: by sejour.lkg.dec.com (5.57/Ultrix4.0) + id AA15569; Fri, 24 May 91 15:00:01 -0400 +Message-Id: <9105241900.AA15569@sejour.lkg.dec.com> +To: tytso@ATHENA.MIT.EDU +Cc: kannan@sejour.lkg.dec.com +Subject: GSS API for SPX ready for testing +Date: Fri, 24 May 91 15:00:00 EDT +From: kannan@sejour.lkg.dec.com + +Ted, + +I have completed the initial implementation of the GSS API for the SPX +mechanism and I've modified the flogin program to use this new +interface. My "standard" GSS library includes the following routines: + +/* + * Offering "standard" GSS API for following mechanism(s) : SPX + * + * Supported jacket routines : + * + * gss_acquire_cred Assume a global identity + * + * gss_release_cred Discard credentials + * + * gss_init_sec_context Initiate a security context with a + * peer application + * + * gss_accept_sec_context Accept a security context from a + * peer application + * + * gss_display_status Convert an API status code to text + * + * gss_indicate_mechs Determine underlying mechanism + * + * gss_display_name Convert opaque name to text + * + * gss_import_name Convert a textual name to API-format + * + * gss_release_name Deallocate API internal name + * + * gss_release_buffer Deallocate a buffer descriptor + * + * gss_release_oid_set Deallocate a set of object identifiers + * + * Unofficial jacket routines : + * + * gss__stash_default_cred Bind credential handle as default + * + * gss__check_authorization Check authorization rights for principal + * + */ + +As you can tell, I have two unofficial routines referred to as "gss__" +instead of "gss_". + +The first, gss__stash_default_cred will set the specified credential as +the default for a process. After calling this routine, GSS_C_NULL_CREDENTIAL +can be used by the calling application to reference the stashed credentials. +Note, if GSS_C_NULL_CREDENTIAL is passed to this routine, success is returned. + +/* + * WARNING: UNOFFICIAL GSSAPI ROUTINE!! + * + * gss__stash_default_cred() - Allows remote peer to bind delegated credential + * handle with remote application. Called by applications to set the + * delegated credentials as the default credentials for a process. + * + * OM_uint32 *minor_status (output) - mechanism specific status code + * gss_cred_id_t delegated_cred_handle (input) - handle for credentials + * received from context initiator. + * + */ + +The second, gss__check_authorization is a bit more controversial. This +routine will check access rights for a principal against an ACL file. +I've added a few additional arguments to make this routine more robust +so that access control decisions can be based on a per service and +possible per resource basis. + +/* + * WARNING: UNOFFICIAL GSSAPI ROUTINE!! + * + * gss__check_authorization() - Check authorization rights for principal + * using the ACL file specified. + * + * OM_uint32 *minor_status (output) - mechanism specific status code + * gss_buffer_t fullname_buffer (input) - principal's printable name + * gss_buffer_t luser_buffer (input) - local user name + * gss_buffer_t acl_file_buffer (input) - acl file name + * gss_buffer_t service_buffer (input) - service name + * int access_mode (input) - type of access (rwx, etc.) + * gss_buffer_t resource_buffer (input) - resource name + * + */ + +I've also defined 3 unofficial constants to describe the access modes. + +#define GSS_C_READ (1 << 0) +#define GSS_C_WRITE (1 << 1) +#define GSS_C_EXECUTE (1 << 2) + +You look at the application source code to see how these routines are +being used. The next message will contain the following files: + + - Makefile, flogin.c fcmd.c flogind.c login.c + +Talk to you later. + + -kannan + diff --git a/src/lib/gssapi/sample/Makefile.bak b/src/lib/gssapi/sample/Makefile.bak new file mode 100644 index 0000000..3dd42fb --- /dev/null +++ b/src/lib/gssapi/sample/Makefile.bak @@ -0,0 +1,396 @@ +# Makefile generated by imake - do not edit! +# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $ + +# $Source$ +# $Author$ +# $Id$ +# + +########################################################################### +# Makefile generated from "Imake.tmpl" and </tmp/IIf.002934> +# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $ +# +# Platform-specific parameters may be set in the appropriate .cf +# configuration files. Site-wide parameters may be set in the file +# site.def. Full rebuilds are recommended if any parameters are changed. +# +# If your C preprocessor doesn't define any unique symbols, you'll need +# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing +# "make Makefile", "make Makefiles", or "make World"). +# +# If you absolutely can't get imake to work, you'll need to set the +# variables at the top of each Makefile as well as the dependencies at the +# bottom (makedepend will do this automatically). +# + +########################################################################### +# platform-specific configuration parameters - edit vaxbsd.cf to change + +# $Source$ +# $Author$ +# $Id$ +# + +########################################################################### +# site-specific configuration parameters - edit site.def to change + +# $Source$ +# $Author$ +# $Id$ +# + +# site: $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $ + + SHELL = /bin/sh + + TOP = ../../../. + CURRENT_DIR = ./lib/gssapi/sample + + AR = ar cq + BOOTSTRAPCFLAGS = + CC = gcc -fstrength-reduce -fpcc-struct-return -pedantic -ansi -Wall -Dunix -Dvax + + COMPRESS = compress + CPP = /lib/cpp $(STD_CPP_DEFINES) + PREPROCESSCMD = gcc -fstrength-reduce -fpcc-struct-return -pedantic -ansi -Wall -Dunix -Dvax -E $(STD_CPP_DEFINES) + INSTALL = install + LD = ld + LDLOCATIONS = + LINT = lint + LINTLIBFLAG = -C + LINTOPTS = -axz + LN = ln -s + MAKE = make + MV = mv + CP = cp + RANLIB = ranlib + RANLIBINSTFLAGS = + RM = rm -f + STD_INCLUDES = + STD_CPP_DEFINES = + STD_DEFINES = + SABER_DEFINES = -I/mit/gnu/vaxlib/gcc-include -Dconst= + EXTRA_LOAD_FLAGS = -Z + EXTRA_LIBRARIES = + TAGS = ctags + ETAGS = etags +STDC_TOP_INCLUDES = -I$(TOP)/include/stdc-incl + + SIGNAL_DEFINES = -DSIGNALRETURNSINT + + INSTPGMFLAGS = -s + + INSTSCRFLAGS = + INSTBINFLAGS = -m 0755 + INSTUIDFLAGS = -o root -m 4755 + INSTLIBFLAGS = -m 0664 + INSTINCFLAGS = -m 0444 + INSTMANFLAGS = -m 0444 + INSTDATFLAGS = -m 0444 + INSTKMEMFLAGS = -o root -m 4755 + + DESTDIR = + + TOP_INCLUDES = -I$(TOP) + + CDEBUGFLAGS = -O + CCOPTIONS = + COMPATFLAGS = + + ALLINCLUDES = $(INCLUDES) $(STD_INCLUDES) $(TOP_INCLUDES) $(EXTRA_INCLUDES) + ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS) + CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES) + LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES) + LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LDLOCATIONS) + LDCOMBINEFLAGS = -X -r + MDFLAGS = -D__STDC__ -I/mit/gnu/vaxlib/gcc-include + + MACROFILE = vaxbsd.cf + RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut + + IMAKE_DEFINES = + + IRULESRC = $(CONFIGSRC) + + IMAKE_CMD = $(IMAKE) -I$(NEWTOP)$(IRULESRC) $(IMAKE_DEFINES) + + ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \ + $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \ + $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES) + +# Kerberos version 5 Build Parameters +# +# $Source$ +# $Author$ +# $Id$ + +P_TERMIOS=-UHasPosixTermiosTrue + +P_FLOCKS=-UHasPosixFileLocksTrue + +P_TYPES=-UHasPosixTypesTrue + +P_SIGTYPE=-UHasVoidSignalReturnTrue + +P_STRINGH=-DHasStringHTrue + +P_BITSIZE=-DBitsize32 -UBitsize16 -UBitsize64 + +P_DBM=-DHasNdbmTrue + +P_INET=-DHasInetTrue + +P_STDLIBH=-UHasStdlibHTrue -UForceStdlibH + +P_TIME_DEFS=-DUseSysTimeH -UUseTimeH + +P_PROTOS=-UProvidePrototypes + +P_NPROTO=-UUseNarrowPrototypes + +P_STDARG=-UUseStdarg + + ARADD = ar cruv + TOP_INCLUDES = -I$(TOP)/include $(STDC_TOP_INCLUDES) + CONFIGSRC = $(TOP)/config + ISODE = /mit/isode/isode-6.8 + PSYFLAGS = -f -h0 -a -s + PEPSY = $(ISODE)/@sys/bin/pepsy + TOUCH = touch + IMAKE = imake + DEPEND = makedepend + UNIFDEF = unifdef + HESDEFS = -DHESIOD + HESLIBS = -lhesiod + + PROCESS_DEFINES = $(P_TERMIOS) $(P_FLOCKS) $(P_TYPES) $(P_SIGTYPE) $(P_STRINGH) $(P_BITSIZE) $(P_DBM) $(P_INET) $(P_STDLIBH) $(P_TIME_DEFS) $(P_PROTOS) $(P_NPROTO) $(P_STDARG) -DUnifdefRan + DESDEFINES = -DBIG -DLSBFIRST + TOPLIBD = $(TOP)/lib + OSLIB = os + OSDEPLIB = $(TOPLIBD)/libos.a + DESLIB = des5 + DESDEPLIB = $(TOPLIBD)/libdes5.a + RSAMD4LIB = md4 + RSAMD4DEPLIB = $(TOPLIBD)/libmd4.a + KRB5LIB = krb5 + KRB5DEPLIB = $(TOPLIBD)/libkrb5.a + CRCLIB = crc32 + CRCDEPLIB = $(TOPLIBD)/libcrc32.a + ISODELIB = -L/mit/isode/isode-6.8/@sys/lib -lisode + + DBMLIB = + DEPKLIB = $(KRB5DEPLIB) $(DESDEPLIB) $(OSDEPLIB) + KLIBLOC = -L$(TOPLIBD) + KLIB = $(KLIBLOC) -l$(KRB5LIB) -l$(DESLIB) -l$(OSLIB) $(ISODELIB) $(COMERRLIB) $(DBMLIB) + KDBDEPLIB = $(TOPLIBD)/libkdb.a + KDBLIB = $(KLIBLOC) -lkdb + KRB425DEPLIB = $(TOPLIBD)/libkrb425.a + KRB425LIB = krb425 + DES425DEPLIB = $(TOPLIBD)/libdes425.a + DES425LIB = des425 + KRB4LIB = -lkrb $(KLIBLOC) -l$(DES425LIB) + KRB4INCLUDES = -I$(TOP)/include/kerberosIV + KRB4DEPLIB = $(DES425DEPLIB) + + SSLIB = -lss + MK_CMDS = mk_cmds + COMERRLIB = -lcom_err + COMPILE_ET = compile_et + + ADMIN_BINDIR = /krb5/admin + ADMIN_MANSUFFIX = 8 + ADMIN_MANDIR = /krb5/man/man8 + SERVER_BINDIR = /krb5/sbin + SERVER_MANSUFFIX = 8 + SERVER_MANDIR = /krb5/man/man8 + CLIENT_BINDIR = /krb5/bin + CLIENT_MANSUFFIX = 1 + CLIENT_MANDIR = /krb5/man/man1 + +# $Source$ +# $Author$ +# $Id$ +# + +########################################################################### +# Imake rules for building libraries, programs, scripts, and data files +# rules: $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $ + +########################################################################### +# start of Imakefile + +# $Source$ +# $Author$ +# $Id$ +# +# Copyright 1991 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# For copying and distribution information, please see the file +# <krb5/copyright.h>. +# + + DEPLIBS = $(DEPKLIB) ../libgssapi.a +LOCAL_LIBRARIES = $(KLIB) ../libgssapi.a + DEFINES = -DDEBUG + +SRCS = flogin.c fcmd.c flogind.c fsh.c fcp.c login.c logutil.c +OBJS = flogin.o fcmd.o flogind.o fsh.o fcp.o login.o logutil.o + +FLOGINSRCS = flogin.c fcmd.c +FLOGINOBJS = flogin.o fcmd.o + +LOGINSRCS = login.c logutil.c +LOGINOBJS = login.o logutil.o + +FLOGINDSRCS = flogind.c logutil.c +FLOGINDOBJS = flogind.o logutil.o + +FSHSRCS = fsh.c fcmd.c +FSHOBJS = fsh.o fcmd.o + +FSHDSRCS = fshd.c +FSHDOBJS = fshd.o + +FCPSRCS = fcp.c fcmd.c +FCPOBJS = fcp.o fcmd.o + +all:: flogin login.gssapi flogind + +flogin: $(FLOGINOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(FLOGINOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) flogin + +login.gssapi: $(LOGINOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(LOGINOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) login.gssapi + +flogind: $(FLOGINDOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(FLOGINDOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) flogind + +fsh: $(FSHOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(FSHOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) fsh + +fshd: $(FSHDOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(FSHDOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) fshd + +fcp: $(FCPOBJS) $(DEPLIBS) + $(RM) $@ + $(CC) -o $@ $(FCPOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) + +clean:: + $(RM) fcp + +saber_flogin: + #load $(ALLDEFINES) $(FLOGINSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_flogin: + #load $(ALLDEFINES) $(FLOGINOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +saber_login.gssapi: + #load $(ALLDEFINES) $(LOGINSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_login.gssapi: + #load $(ALLDEFINES) $(LOGINOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +saber_flogind: + #load $(ALLDEFINES) $(FLOGINDSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_flogind: + #load $(ALLDEFINES) $(FLOGINDOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +saber_fsh: + #load $(ALLDEFINES) $(FSHSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_fsh: + #load $(ALLDEFINES) $(FSHOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +saber_fshd: + #load $(ALLDEFINES) $(FSHDSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_fshd: + #load $(ALLDEFINES) $(FSHDOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +saber_fcp: + #load $(ALLDEFINES) $(FCPSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +osaber_fcp: + #load $(ALLDEFINES) $(FCPOBJS) + $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES) + +SRCS=$(SERVERSRCS) $(CLIENTSRCS) + +depend:: + $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) $(MDFLAGS) -- $(SRCS) + +########################################################################### +# common rules for all Makefiles - do not edit + +emptyrule:: + +clean:: + $(RM_CMD) \#* + +Makefile:: Imakefile + $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) -s Makefile.new + $(MAKE) -f Makefile.new noop + -@if [ -f Makefile ]; then \ + echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ + $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ + fi + $(MV) Makefile.new Makefile + +noop:: + +tags:: + $(TAGS) -w *.[ch] + $(ETAGS) *.[ch] + +saber: + #load $(ALLDEFINES) $(SABER_DEFINES) $(SRCS) + #setopt load_flags $(ALLDEFINES) $(SABER_DEFINES) + +osaber: + #load $(ALLDEFINES) $(OBJS) + +########################################################################### +# empty rules for directories that do not have SUBDIRS - do not edit + +install:: + @echo "install in $(CURRENT_DIR) done" + +install.man:: + @echo "install.man in $(CURRENT_DIR) done" + +Makefiles:: + +includes:: + +########################################################################### +# dependencies generated by makedepend + +# DO NOT DELETE diff --git a/src/lib/gssapi/sample/gssapi.mail b/src/lib/gssapi/sample/gssapi.mail new file mode 100644 index 0000000..fce9209 --- /dev/null +++ b/src/lib/gssapi/sample/gssapi.mail @@ -0,0 +1,54 @@ +BABYL OPTIONS: +Version: 5 +Labels: +Note: This is the header of an rmail file. +Note: If you are seeing it in rmail, +Note: it means the file has no messages in it. + +1,, +Received: by E40-PO.MIT.EDU (5.45/4.7) id AA21631; Fri, 31 May 91 18:18:51 EDT +Received: from uucp-gw-1.pa.dec.com by ATHENA.MIT.EDU with SMTP + id AA27178; Fri, 31 May 91 18:16:24 EDT +Received: by uucp-gw-1.pa.dec.com; id AA17698; Fri, 31 May 91 10:48:08 -0700 +Received: by sejour.lkg.dec.com (5.57/Ultrix4.0) + id AA11377; Fri, 31 May 91 13:51:46 -0400 +Message-Id: <9105311751.AA11377@sejour.lkg.dec.com> +To: tytso@ATHENA.MIT.EDU +Cc: kannan@sejour.lkg.dec.com +Subject: Re: testing GSS API +In-Reply-To: Your message of Thu, 30 May 91 18:25:28 -0400. + <9105302225.AA24140@tsx-11.MIT.EDU> +Date: Fri, 31 May 91 13:51:44 EDT +From: kannan@sejour.lkg.dec.com + +*** EOOH *** +To: tytso@ATHENA.MIT.EDU +Cc: kannan@sejour.lkg.dec.com +Subject: Re: testing GSS API +In-Reply-To: Your message of Thu, 30 May 91 18:25:28 -0400. + <9105302225.AA24140@tsx-11.MIT.EDU> +Date: Fri, 31 May 91 13:51:44 EDT +From: kannan@sejour.lkg.dec.com + +Here is the new rlogin code. BTW, it is also being distributed with +the SPX v2.1 kit. + +I'm sending you the following files: + + Makefile, flogin.c, flogind.c, and login.c + +> The real test is whether or not the application runs. + +I agree. Does this mean that you will implement the "unofficial" GSS API +routines used in the flogin code? + + -kannan + +========== Makefile ====================== + +===================== flogin.c ======================== + +===================== flogind.c ================ + +===================== login.c ====================== +
\ No newline at end of file diff --git a/src/lib/gssapi/sample/kitest.c b/src/lib/gssapi/sample/kitest.c new file mode 100644 index 0000000..0ec048c --- /dev/null +++ b/src/lib/gssapi/sample/kitest.c @@ -0,0 +1,742 @@ +/* KITEST-MASTER.C */ +/* */ +/* Program to build GSSAPI-compliant Kerberos authentication packets, using */ +/* the Kerberos V5 (Beta 2) GSSAPI implementation, and attempt to */ +/* authenticate to a DCE/GSSAPI implementation. */ +/* */ +/* Since both GSSAPI implementations share the same routine names, two */ +/* executables are built by linking against either the DCE/GSSAPI or the */ +/* Kerberos V5 GSSAPI library. This file is compiled with the preprocessor */ +/* name KERBEROS defined if it is to invoke the Kerberos API, and with DCE */ +/* defined if it is to link against the DCE/GSSAPI. */ +/* */ +/* Invocation should specify two parameters - */ +/* 1) Name of initiating principal */ +/* 2) Name of accepting principal */ +/* */ +/* A flag '-S' is used to specify the name of the file that process will */ +/* activate as a slave. */ +/* */ +/* So to test, for example, Kerberos against Kerberos, and assuming that */ +/* the executable is called kitest-krb, you'd set up a Kerberos credential */ +/* for <client-name> using kinit, and arrange for a server Kerberos */ +/* credential for <server-name> to be available in a keytable, and issue */ +/* the command: */ +/* kitest-krb -S kitest-krb <client-name> <server-name> */ +/* */ +/* The original process becomes the context initiator, while the spawned */ +/* subprocess (running the executable specified after the -S flag) is */ +/* expected to act as the context acceptor. */ + +#if defined(KERBEROS) && defined(DCE) +#error "Both KERBEROS and DCE specified" +#endif + +#if !defined(KERBEROS) && !defined(DCE) +#error "Neither KERBEROS nor DCE defined" +#endif + +/* You need to create links from krb-gssapi.h to the Kerberos gssapi.h, and */ +/* from dce-gssapi.h to the DCE gssapi.h. */ +#ifdef KERBEROS +#include "krb-gssapi.h" +#endif + +#ifdef DCE +#include "dce-gssapi.h" +#endif + + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <netdb.h> + +#ifndef GSS_ERROR +#define GSS_ERROR(x) (x & 0xffff0000) +/* The Kerberos gssapi.h doesn't define this macro. */ +#endif + +#define DOWN_CHANNEL 3 +/* Don't understand why stdin doesn't work here, but channel 3 seems to */ +/* work fine. */ + +#define INITIAL_CHILD_MESSAGES 7 + +extern int errno; + +int master = 0; +int inpipe[2]; +int outpipe[2]; +int errpipe[2]; + +gss_name_t source_internal_name; +gss_name_t target_internal_name; +gss_name_t source_authenticated_name; +gss_buffer_desc source_name_buffer; +gss_buffer_desc target_name_buffer; + +gss_cred_id_t my_cred_handle; +gss_cred_id_t delegated_cred_handle; +gss_ctx_id_t my_ctx_handle; +gss_OID_set actual_cred_mech_set; +gss_OID actual_ctx_mech_type; +OM_uint32 actual_cred_time_rec; +OM_uint32 actual_ctx_time_rec; +gss_buffer_desc token_to_send; +gss_buffer_desc token_received; +int actual_ret_flags; +struct gss_channel_bindings_struct my_channel_bindings; + +char source_name[512]; +char target_name[512]; + +char my_host_name[50]; +char my_internet_address[4]; +struct hostent * my_hostent; + +unsigned char received_token_buffer[2048]; +unsigned received_length; + +OM_uint32 major_status; +OM_uint32 kept_status; +OM_uint32 minor_status; + +int subprocess_pid = 0; + +char line_buffer[128]; +int chars_read; + +void indicate_data(void) { + fprintf(stderr, "\a\n"); + fflush(stderr); +} + +void send_data(void * ptr, unsigned length) { + unsigned char length_buf[2]; + unsigned char * char_ptr; + int data_sent; + + char_ptr = (unsigned char *)ptr; + + length_buf[0] = length & 0xff; + length_buf[1] = (length & 0xff00) >> 8; + + if (master) { +/* Data is sent via inpipe. */ + errno = 0; + if ((data_sent = write(inpipe[1], length_buf, 2)) != 2) { + fprintf(stderr, + "Write of length sent %d bytes, expected 2\n", + data_sent); + fflush(stderr); + if (data_sent == -1) { + fprintf(stderr, + "Errno: %d\n", + errno); + fflush(stderr); + }; + }; + errno = 0; + if ((data_sent =write(inpipe[1], ptr, length)) != length) { + fprintf(stderr, + "Write of length sent %d bytes, expected 2\n", + data_sent); + fflush(stderr); + if (data_sent == -1) { + fprintf(stderr, + "Errno: %d\n", + errno); + fflush(stderr); + }; + }; + fprintf(stderr, "Sending data (length = %d):\n", length); + fprintf(stderr, " %2.2X %2.2X %2.2X %2.2X %2.2X...\n", + char_ptr[0], char_ptr[1], char_ptr[2], + char_ptr[3], char_ptr[4]); + } else { +/* Data is sent via stdout, and a data indication on stderr. */ + fwrite(length_buf, 2, 1, stdout); + fwrite(ptr, length, 1, stdout); + fflush(stdout); + indicate_data(); + }; +} + +void receive_data(void * ptr, unsigned * length) { + unsigned char length_buf[2]; + unsigned char * char_ptr; + int data_read; + + char_ptr = (unsigned char *)ptr; + + if (master) { +/* Data is received via outpipe. A data indication is assumed to have been */ +/* received on errpipe, otherwise this routine will hang. */ + read(outpipe[0], length_buf, 2); + *length = length_buf[0] | (length_buf[1]<<8); + read(outpipe[0], ptr, *length); + } else { +/* Data is received on fd3 */ + errno = 0; + if ((data_read = read(DOWN_CHANNEL, length_buf, 2)) != 2) { + fprintf(stderr, + "Error: received %d bytes for length, expecting 2\n", + data_read); + fflush(stderr); + if (data_read == -1) { + fprintf(stderr, "errno: %d\n", errno); + fflush(stderr); + }; + }; + + *length = length_buf[0] | (length_buf[1]<<8); + + errno = 0; + if ((data_read = read(DOWN_CHANNEL, ptr, *length)) != *length) { + fprintf(stderr, + "Error: received %d bytes for data, expecting %d\n", + data_read, *length); + fflush(stderr); + if (data_read == -1) { + fprintf(stderr, "errno: %d\n", errno); + fflush(stderr); + }; + }; + + fprintf(stderr, "Received data (length = %d):\n", *length); + fprintf(stderr, " %2.2X %2.2X %2.2X %2.2X %2.2X...\n", + char_ptr[0], char_ptr[1], char_ptr[2], + char_ptr[3], char_ptr[4]); + + }; +} + +int read_subproc_line(char * ptr, unsigned buf_length) { +/* Returns length of data read, or zero if binary data waiting. */ + int bytes_read = 0; + int finished = 0; + if (!master) { + fprintf(stderr, "Error: Child called read_subproc_data\n"); + fflush(stderr); + exit(2); + } else { + while (!finished) { + read(errpipe[0], &ptr[bytes_read], 1); + if (ptr[bytes_read] == '\n') finished = 1; + if (bytes_read >= buf_length) finished = 1; + bytes_read ++; + }; + if (bytes_read == 2 && ptr[0] == '\a') return 0; + else return bytes_read; + }; +} + +void display_error(char * where, OM_uint32 maj_stat, OM_uint32 min_stat) { + int context = 0; + OM_uint32 major_status, minor_status; + gss_buffer_desc message_buffer; + + fprintf(stderr, "Error: %s\n", where); + fprintf(stderr, "Major status (%d) (min = %d):\n", maj_stat, min_stat); + fflush(stderr); + do { + message_buffer.length = 0; + message_buffer.value = NULL; + major_status = gss_display_status(&minor_status, + maj_stat, + GSS_C_GSS_CODE, + GSS_C_NULL_OID, + &context, + &message_buffer); + fprintf(stderr, + " message_buffer.length = %u, message_buffer.value = %p\n", + message_buffer.length, message_buffer.value); + fflush(stderr); + if (message_buffer.length = 0) { + fprintf(stderr, + " %.*s\n", + message_buffer.length, + message_buffer.value); + major_status = gss_release_buffer(&minor_status, &message_buffer); + } else { + fprintf(stderr, "-- no message --\n"); + /* If we've been asked to translate an invalid status code */ + }; + fflush(stderr); + + } while (context != 0); + fprintf(stderr, "Minor status:\n"); + fflush(stderr); + major_status = gss_display_status(&minor_status, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &context, + &message_buffer); + fprintf(stderr, + " %.*s\n", + message_buffer.length, + message_buffer.value); + fflush(stderr); + + major_status = gss_release_buffer(&minor_status, &message_buffer); + +} + +void import_names(void) { + + source_name_buffer.value = (void *)&source_name[0]; + source_name_buffer.length = strlen(source_name); + + major_status = gss_import_name(&minor_status, + &source_name_buffer, + GSS_C_NULL_OID, + &source_internal_name); + + if (major_status != GSS_S_COMPLETE) + display_error("Importing source principal", major_status, minor_status); + + target_name_buffer.value = (void *)&target_name[0]; + target_name_buffer.length = strlen(target_name); + + major_status = gss_import_name(&minor_status, + &target_name_buffer, + GSS_C_NULL_OID, + &target_internal_name); + + if (major_status != GSS_S_COMPLETE) + display_error("Importing target principal", major_status, minor_status); + +} + + +void alarm_handler(int sig) { + fprintf(stderr, "SIGALRM received, terminating subprocess\n"); + fflush(stderr); + kill(subprocess_pid, SIGTERM); + exit(0); +} + + +void flush_subprocess_message_queue_and_exit(void) { + + signal(SIGALRM, alarm_handler); + alarm(10); + + do { + chars_read = read_subproc_line(line_buffer, + sizeof(line_buffer)); + if (chars_read == 0) { + fprintf(stderr, + "Unexpected binary data received from child\n"); + fflush(stderr); + receive_data(received_token_buffer, + &received_length); + } else { + fprintf(stderr,"CHILD> %.*s", chars_read, line_buffer); + }; + fflush(stderr); + } while (1); +} + +void sigpipe_handler(int sig) { + fprintf(stderr, "SIGPIPE received, flushing subprocess message queue\n"); + fflush(stderr); + flush_subprocess_message_queue_and_exit(); +} + +int main(int argc, char *argv[]) { + + int c; + int errflg = 0; + char * image_name; + int pid; + + int i; + + extern int optind, opterr; + extern char * optarg; + + int blocking; + + while ((c = getopt(argc, argv, "S:")) != EOF) { + switch (c) { + case 'S' : master = 1; + image_name = optarg; + break; + case '?' : errflg++; + break; + }; + }; + + if (optind < argc) { + strncpy(source_name, argv[optind++], sizeof(source_name)-1); + } else { + fprintf(stderr, "Error: Source name (prin-1) missing\n"); + errflg++; + }; + + if (optind < argc) { + strncpy(target_name, argv[optind++], sizeof(source_name)-1); + } else { + fprintf(stderr, "Error: Target name (prin-2) missing\n"); + errflg++; + }; + + if (optind < argc) { + fprintf(stderr, "Error: too many parameters\n"); + errflg++; + }; + + if (errflg) { + fprintf(stderr, "Usage: %s -S <subprocess> <princ-1> <princ-2>\n", argv[0]); + exit(2); + }; + + gethostname(my_host_name, sizeof(my_host_name)); + my_hostent = gethostbyname(my_host_name); + memcpy(&my_internet_address, my_hostent->h_addr_list[0], 4); + + fprintf(stderr,"Host: '%s', %u.%u.%u.%u\n", + my_host_name, + my_internet_address[0], + my_internet_address[1], + my_internet_address[2], + my_internet_address[3]); + + my_channel_bindings.initiator_addrtype = GSS_C_AF_INET; + my_channel_bindings.initiator_address.length = 4; + my_channel_bindings.initiator_address.value = my_internet_address; + + my_channel_bindings.acceptor_addrtype = GSS_C_AF_INET; + my_channel_bindings.acceptor_address.length = 4; + my_channel_bindings.acceptor_address.value = my_internet_address; + + my_channel_bindings.application_data.length = 0; + my_channel_bindings.application_data.value = NULL; + + my_ctx_handle = GSS_C_NO_CONTEXT; + + if (!master) { + +/* Subprocess. */ + + fprintf(stderr, "Importing names\n"); + fflush(stderr); + + import_names(); + + fprintf(stderr, "Calling acquire_cred\n"); + fflush(stderr); + + major_status = gss_acquire_cred(&minor_status, + target_internal_name, + 60 * 60 * 24, + GSS_C_NULL_OID_SET, + GSS_C_ACCEPT, + &my_cred_handle, + &actual_cred_mech_set, + &actual_cred_time_rec); + + if (major_status != GSS_S_COMPLETE) { + display_error("Acquiring ACCEPT credential for target principal", + major_status, minor_status); + while (1) ; + }; + + fprintf(stderr, "Returned from acquire_cred, waiting for token from parent\n"); + fflush(stderr); + + do { + + receive_data(received_token_buffer, + &received_length); + token_received.value = (void *)received_token_buffer; + token_received.length = received_length; + + fprintf(stderr, "Got token, calling accept_sec_context\n"); + fflush(stderr); + + major_status = gss_accept_sec_context(&minor_status, + &my_ctx_handle, + my_cred_handle, + &token_received, + &my_channel_bindings, + &source_authenticated_name, + &actual_ctx_mech_type, + &token_to_send, + &actual_ret_flags, + &actual_ctx_time_rec, + &delegated_cred_handle); + kept_status = major_status; + + if (GSS_ERROR(major_status)) { + display_error("ACCEPT_SEC_CONTEXT", + major_status, minor_status); + while (1) ; + }; + + if (token_to_send.length != 0) { + send_data(token_to_send.value, token_to_send.length); + major_status = gss_release_buffer(&minor_status, + &token_to_send); + }; + + if (kept_status & GSS_S_CONTINUE_NEEDED) { + receive_data(received_token_buffer, + &received_length); + token_received.value = (void *)received_token_buffer; + token_received.length = received_length; + }; + + } while (kept_status & GSS_S_CONTINUE_NEEDED); + + if (!GSS_ERROR(kept_status)) { + fprintf(stderr, "Authenticated context established\n"); + } else { + fprintf(stderr, "Context not established\n"); + }; + fflush(stderr); + while (1) ; + } else { +/* We need to create three pipes - inpipe, outpipe and errpipe, to which */ +/* the subprocess will connect its fd3, stdout and stderr channels. */ + + if (pipe(inpipe) < 0) { + fprintf(stderr, "Error: Can't make inpipe\n"); + exit(2); + }; + if (pipe(outpipe) < 0) { + fprintf(stderr, "Error: Can't make outpipe\n"); + exit(2); + }; + if (pipe(errpipe) < 0) { + fprintf(stderr, "Error: Can't make errpipe\n"); + exit(2); + }; + + if ((subprocess_pid = fork()) == 0) { +/* This is the slave subprocess in a two-process chain. Connect inpipe, */ +/* outpipe and errpipe to fd3, stderr and stdout, and then exec the slave */ +/* image. */ + fprintf(stderr, "CHILD: forked, closing pipes\n"); + fflush(stderr); + + close(inpipe[1]); /* Close write end of inpipe */ + close(outpipe[0]); /* Close read end of outpipe */ + close(errpipe[0]); /* Close read end of errpipe */ + + + write (errpipe[1], + "Child process forked (write to errpipe[1])\n", + strlen("Child process forked (write to errpipe[1])\n") + ); + + if (dup2(inpipe[0], DOWN_CHANNEL) == -1) { + fprintf(stderr, "CHILD: Can't dup2 inpipe[0]\n"); + fflush(stderr); + }; + /* Attach inpipe to fd3 */ + if (dup2(outpipe[1], 1) == -1) { + fprintf(stderr, "CHILD: Can't dup2 outpipe[1]\n"); + fflush(stderr); + }; + /* Attach outpipe to stdout */ + if (dup2(errpipe[1], 2) == -1) { + fprintf(stderr, "CHILD: Can't dup2 errpipe[1]\n"); + fflush(stderr); + }; + /* Attach errpipe to stderr */ + + write (2, + "Child process forked (write to fd2)\n", + strlen("Child process forked (write to fd2)\n") + ); + + fprintf(stderr, "Execing %s\n", image_name); + fflush(stderr); + + execl(image_name, image_name, source_name, target_name, (char *)0); + + fprintf(stderr, "Error: Couldn't exec %s\n", image_name); + exit(2); + + } else if (subprocess_pid < 0) { + fprintf(stderr, "Error: Fork returned %d\n", subprocess_pid); + exit(2); + } else { +/* This is the master process in a two-process chain. The slave process */ +/* has connected inpipe, outpipe and errpipe to its fd3, stdout and */ +/* stderr. We have to use the other ends. */ + + + close(inpipe[0]); /* Close read end of inpipe */ + close(outpipe[1]); /* Close write end of outpipe */ + close(errpipe[1]); /* Close write end of errpipe */ + +/* A simple protocol will be used between master and slave processes. The */ +/* subprocess (slave) will always expect that data received on its inpipe */ +/* will be binary messages, preceeded by a two-byte count. Messages from */ +/* slave to master will be sent on the errpipe channel if they are text */ +/* messages, and on outpipe if they are binary data (preceeded as above by */ +/* a two-byte count field). The presence of a binary message in the */ +/* outpipe will be indicated by writing the sequence "\a\n" to errpipe. */ +/* This protocol is implemented in the master by the routine */ +/* read_subproc_line, which reads a single line of text from the */ +/* subprocess, returning either its length, or zero to indicate that binary */ +/* data is waiting. Binary data is received by either process by invoking */ +/* the receive_data routine, and sent by invoking the send_data routine. */ +/* The receive_data routine will block until the data is available, so */ +/* care should be taken in the master not to call this routine unless a */ +/* data indication has already been received. */ + +/* Master: */ + signal(SIGPIPE, sigpipe_handler); + +/* The child will send us messages on start-up (at least */ +/* INITIAL_CHILD_MESSAGES of them), so we'll read them here to make sure we */ +/* catch a sleepy child early. */ + + fprintf(stderr, "Parent waiting for wake-up call from child...\n"); + fflush(stderr); + + signal(SIGALRM, alarm_handler); + alarm(10); + + for (i=0; i<INITIAL_CHILD_MESSAGES; i++) { + chars_read = read_subproc_line(line_buffer, + sizeof(line_buffer)); + + if (chars_read == 0) { + fprintf(stderr, + "Unexpected binary data received from child\n"); + fflush(stderr); + receive_data(received_token_buffer, + &received_length); + } else { + fprintf(stderr,"CHILD> %.*s", chars_read, line_buffer); + }; + fflush(stderr); + + }; + + alarm(0); + + fprintf(stderr, "Parent continuing, importing names...\n"); + fflush(stderr); + + import_names(); + + fprintf(stderr, "Parent got names...\n"); + fflush(stderr); + +#ifdef KERBEROS + +/* This version of the acquire_cred code requests the client credential */ +/* explicitly by name; the DCE version uses no name, meaning "give me a */ +/* to the default credential. */ + + fprintf(stderr, "Parent calling acquire_cred...\n"); + fflush(stderr); + + major_status = gss_acquire_cred(&minor_status, + source_internal_name, + 60 * 60 * 24, + GSS_C_NULL_OID_SET, + GSS_C_INITIATE, + &my_cred_handle, + &actual_cred_mech_set, + &actual_cred_time_rec); + + fprintf(stderr, "Parent returned from acquire_cred.\n"); + fflush(stderr); + +#endif +#ifdef DCE + major_status = gss_acquire_cred(&minor_status, + GSS_C_NO_NAME, + 60 * 60 * 24, + GSS_C_NULL_OID_SET, + GSS_C_INITIATE, + &my_cred_handle, + &actual_cred_mech_set, + &actual_cred_time_rec); +#endif + if (major_status != GSS_S_COMPLETE) + display_error("Acquiring INITIATE credential for source principal", + major_status, minor_status); + + + token_received.length = 0; + token_received.value = NULL; + + do { + + fprintf(stderr, "Parent calling init_sec_ctx...\n"); + fflush(stderr); + + major_status = gss_init_sec_context(&minor_status, + my_cred_handle, + &my_ctx_handle, + target_internal_name, + GSS_C_NULL_OID, + GSS_C_MUTUAL_FLAG, + 60 * 60 * 23, + &my_channel_bindings, + &token_received, + &actual_ctx_mech_type, + &token_to_send, + &actual_ret_flags, + &actual_ctx_time_rec); + + fprintf(stderr, "Parent returned from init_sec_ctx...\n"); + fflush(stderr); + + kept_status = major_status; + + if (GSS_ERROR(major_status)) + display_error("INIT_SEC_CONTEXT", + major_status, minor_status); + + if (token_to_send.length != 0) { + + fprintf(stderr, "Parent transmitting token...\n"); + fflush(stderr); + + send_data(token_to_send.value, token_to_send.length); + major_status = gss_release_buffer(&minor_status, + &token_to_send); + }; + + if (kept_status & GSS_S_CONTINUE_NEEDED) { + signal(SIGALRM, alarm_handler); + alarm(30); + while ((chars_read = read_subproc_line(line_buffer, + sizeof(line_buffer)) + ) != 0) { + fprintf(stderr, "CHILD> %.*s", chars_read, line_buffer); + }; + alarm(0); + receive_data(received_token_buffer, + &received_length); + token_received.value = (void *)received_token_buffer; + token_received.length = received_length; + }; + + } while (kept_status & GSS_S_CONTINUE_NEEDED); + + if (!GSS_ERROR(kept_status)) { + fprintf(stderr, "Authenticated context established\n"); + } else { + fprintf(stderr, "Context not established\n"); + }; + fflush(stderr); + + flush_subprocess_message_queue_and_exit(); + + }; + }; +} diff --git a/src/lib/gssapi/sample/logutil.c b/src/lib/gssapi/sample/logutil.c new file mode 100644 index 0000000..d1a5350 --- /dev/null +++ b/src/lib/gssapi/sample/logutil.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)login.c 5.1 (Berkeley) 9/27/88"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <utmp.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/stat.h> + +#define UTMPFILE "/etc/utmp" +#define WTMPFILE "/usr/adm/wtmp" + +void +login(ut) + struct utmp *ut; +{ + register int fd; + int tty; + off_t lseek(); + + tty = ttyslot(); + if (tty > 0 && (fd = open(UTMPFILE, O_WRONLY, 0)) >= 0) { + (void)lseek(fd, (long)(tty * sizeof(struct utmp)), L_SET); + (void)write(fd, (char *)ut, sizeof(struct utmp)); + (void)close(fd); + } + if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) >= 0) { + (void)write(fd, (char *)ut, sizeof(struct utmp)); + (void)close(fd); + } +} +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logout.c 5.1 (Berkeley) 8/31/88"; +#endif /* LIBC_SCCS and not lint */ + +logout(line) + register char *line; +{ + register FILE *fp; + struct utmp ut; + int rval; + time_t time(); + + if (!(fp = fopen(UTMPFILE, "r+"))) + return(0); + rval = 1; + while (fread((char *)&ut, sizeof(struct utmp), 1, fp) == 1) { + if (!ut.ut_name[0] || + strncmp(ut.ut_line, line, sizeof(ut.ut_line))) + continue; + bzero(ut.ut_name, sizeof(ut.ut_name)); + bzero(ut.ut_host, sizeof(ut.ut_host)); + (void)time(&ut.ut_time); + (void)fseek(fp, (long)-sizeof(struct utmp), L_INCR); + (void)fwrite((char *)&ut, sizeof(struct utmp), 1, fp); + (void)fseek(fp, (long)0, L_INCR); + rval = 0; + } + (void)fclose(fp); + return(rval); +} +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)logwtmp.c 5.2 (Berkeley) 9/20/88"; +#endif /* LIBC_SCCS and not lint */ + +logwtmp(line, name, host) + char *line, *name, *host; +{ + struct utmp ut; + struct stat buf; + int fd; + time_t time(); + char *strncpy(); + + if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (!fstat(fd, &buf)) { + (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); + (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); + (void)time(&ut.ut_time); + if (write(fd, (char *)&ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + (void)ftruncate(fd, buf.st_size); + } + (void)close(fd); +} diff --git a/src/lib/krb5.saber.source b/src/lib/krb5.saber.source new file mode 100644 index 0000000..a4c374a --- /dev/null +++ b/src/lib/krb5.saber.source @@ -0,0 +1,18 @@ +setopt load_flags -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES +load /mit/krb5/src/lib/cryptoconf.c /mit/krb5/src/lib/syslog.c /mit/krb5/src/lib/strdup.c + +load /mit/krb5/src/lib/krb/addr_comp.c /mit/krb5/src/lib/krb/addr_order.c /mit/krb5/src/lib/krb/addr_srch.c /u2/krb5/lib/krb/bld_pr_ext.o /u2/krb5/lib/krb/bld_princ.o /mit/krb5/src/lib/krb/conv_princ.c /mit/krb5/src/lib/krb/copy_addrs.c /mit/krb5/src/lib/krb/copy_auth.c /mit/krb5/src/lib/krb/copy_athctr.c /mit/krb5/src/lib/krb/copy_checksum.c /mit/krb5/src/lib/krb/copy_creds.c /mit/krb5/src/lib/krb/copy_data.c /mit/krb5/src/lib/krb/copy_key.c /mit/krb5/src/lib/krb/copy_princ.c /mit/krb5/src/lib/krb/copy_tick.c /mit/krb5/src/lib/krb/cp_key_cnt.c /mit/krb5/src/lib/krb/decode_kdc.c /mit/krb5/src/lib/krb/decrypt_tk.c /mit/krb5/src/lib/krb/encode_kdc.c /mit/krb5/src/lib/krb/encrypt_tk.c /mit/krb5/src/lib/krb/free_rtree.c /mit/krb5/src/lib/krb/faddr_ordr.c /mit/krb5/src/lib/krb/gc_frm_kdc.c /mit/krb5/src/lib/krb/gc_via_tgt.c /mit/krb5/src/lib/krb/gc_2tgt.c /mit/krb5/src/lib/krb/gen_seqnum.c /mit/krb5/src/lib/krb/gen_subkey.c /mit/krb5/src/lib/krb/get_creds.c /mit/krb5/src/lib/krb/get_in_tkt.c /mit/krb5/src/lib/krb/in_tkt_pwd.c /mit/krb5/src/lib/krb/in_tkt_sky.c /mit/krb5/src/lib/krb/kdc_rep_dc.c /mit/krb5/src/lib/krb/krbconfig.c /mit/krb5/src/lib/krb/mk_error.c /mit/krb5/src/lib/krb/mk_priv.c /mit/krb5/src/lib/krb/mk_rep.c /mit/krb5/src/lib/krb/mk_req.c /mit/krb5/src/lib/krb/mk_req_ext.c /mit/krb5/src/lib/krb/mk_safe.c /mit/krb5/src/lib/krb/parse.c /mit/krb5/src/lib/krb/pr_to_salt.c /mit/krb5/src/lib/krb/princ_comp.c /mit/krb5/src/lib/krb/rd_error.c /mit/krb5/src/lib/krb/rd_priv.c /mit/krb5/src/lib/krb/rd_rep.c /mit/krb5/src/lib/krb/rd_req.c /mit/krb5/src/lib/krb/rd_req_sim.c /mit/krb5/src/lib/krb/rd_req_dec.c /mit/krb5/src/lib/krb/rd_safe.c /mit/krb5/src/lib/krb/recvauth.c /mit/krb5/src/lib/krb/sendauth.c /mit/krb5/src/lib/krb/send_tgs.c /mit/krb5/src/lib/krb/srv_rcache.c /mit/krb5/src/lib/krb/tgtname.c /mit/krb5/src/lib/krb/unparse.c /mit/krb5/src/lib/krb/walk_rtree.c + +load -DPEPSY_LINKABLE_FUNCS -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES /u2/krb5/src/lib/asn.1/KRB5_tables.c /mit/krb5/src/lib/asn.1/encode.c /mit/krb5/src/lib/asn.1/decode.c /mit/krb5/src/lib/asn.1/adat2kadat.c /mit/krb5/src/lib/asn.1/addr2kaddr.c /mit/krb5/src/lib/asn.1/adr2kadr.c /mit/krb5/src/lib/asn.1/aprp2kaprp.c /mit/krb5/src/lib/asn.1/aprq2kaprq.c /mit/krb5/src/lib/asn.1/arep2karep.c /mit/krb5/src/lib/asn.1/auth2kauth.c /mit/krb5/src/lib/asn.1/cvt_flags.c /mit/krb5/src/lib/asn.1/ck2kck.c /mit/krb5/src/lib/asn.1/edat2kedat.c /mit/krb5/src/lib/asn.1/ekrp2kekrp.c /mit/krb5/src/lib/asn.1/enck2kkey.c /mit/krb5/src/lib/asn.1/err2kerr.c /mit/krb5/src/lib/asn.1/etpt2ketpt.c /mit/krb5/src/lib/asn.1/g2unix.c /mit/krb5/src/lib/asn.1/kadat2adat.c /mit/krb5/src/lib/asn.1/kaddr2addr.c /mit/krb5/src/lib/asn.1/kadr2adr.c /mit/krb5/src/lib/asn.1/kaprp2aprp.c /mit/krb5/src/lib/asn.1/kaprq2aprq.c /mit/krb5/src/lib/asn.1/karep2arep.c /mit/krb5/src/lib/asn.1/kauth2auth.c /mit/krb5/src/lib/asn.1/kck2ck.c /mit/krb5/src/lib/asn.1/kdcr2kkdcr.c /mit/krb5/src/lib/asn.1/kdcr2ktgsr.c /mit/krb5/src/lib/asn.1/kedat2edat.c /mit/krb5/src/lib/asn.1/kekrp2ekrp.c /mit/krb5/src/lib/asn.1/kerr2err.c /mit/krb5/src/lib/asn.1/ketpt2etpt.c /mit/krb5/src/lib/asn.1/kkdcr2kdcr.c /mit/krb5/src/lib/asn.1/kkey2enck.c /mit/krb5/src/lib/asn.1/klsrq2lsrq.c /mit/krb5/src/lib/asn.1/kprep2prep.c /mit/krb5/src/lib/asn.1/kprin2prin.c /mit/krb5/src/lib/asn.1/kpriv2priv.c /mit/krb5/src/lib/asn.1/ksafe2safe.c /mit/krb5/src/lib/asn.1/ktran2tran.c /mit/krb5/src/lib/asn.1/ktgrq2tgrq.c /mit/krb5/src/lib/asn.1/ktgsr2kdcr.c /mit/krb5/src/lib/asn.1/ktkt2tkt.c /mit/krb5/src/lib/asn.1/lsrq2klsrq.c /mit/krb5/src/lib/asn.1/prep2kprep.c /mit/krb5/src/lib/asn.1/prin2kprin.c /mit/krb5/src/lib/asn.1/priv2kpriv.c /mit/krb5/src/lib/asn.1/qbuf2data.c /mit/krb5/src/lib/asn.1/safe2ksafe.c /mit/krb5/src/lib/asn.1/tran2ktran.c /mit/krb5/src/lib/asn.1/tgrq2ktgrq.c /mit/krb5/src/lib/asn.1/tkt2ktkt.c /mit/krb5/src/lib/asn.1/u2gen.c /mit/krb5/src/lib/asn.1/kasrp2kdcr.c /mit/krb5/src/lib/asn.1/kpwd2pwd.c /mit/krb5/src/lib/asn.1/kpwds2pwds.c /mit/krb5/src/lib/asn.1/pwd2kpwd.c /mit/krb5/src/lib/asn.1/pwds2kpwds.c + +load /mit/krb5/src/lib/free/f_addr.c /mit/krb5/src/lib/free/f_address.c /mit/krb5/src/lib/free/f_arep_enc.c /mit/krb5/src/lib/free/f_ap_rep.c /mit/krb5/src/lib/free/f_ap_req.c /mit/krb5/src/lib/free/f_authdata.c /mit/krb5/src/lib/free/f_authent.c /mit/krb5/src/lib/free/f_cksum.c /mit/krb5/src/lib/free/f_creds.c /mit/krb5/src/lib/free/f_cred_cnt.c /mit/krb5/src/lib/free/f_enc_kdc.c /mit/krb5/src/lib/free/f_enc_tkt.c /mit/krb5/src/lib/free/f_error.c /mit/krb5/src/lib/free/f_kdc_rep.c /mit/krb5/src/lib/free/f_kdc_req.c /mit/krb5/src/lib/free/f_keyblock.c /mit/krb5/src/lib/free/f_last_req.c /mit/krb5/src/lib/free/f_padata.c /mit/krb5/src/lib/free/f_princ.c /mit/krb5/src/lib/free/f_priv.c /mit/krb5/src/lib/free/f_priv_enc.c /mit/krb5/src/lib/free/f_safe.c /mit/krb5/src/lib/free/f_ticket.c /mit/krb5/src/lib/free/f_tickets.c /mit/krb5/src/lib/free/f_tgt_cred.c /mit/krb5/src/lib/free/f_tkt_auth.c + +load /mit/krb5/src/lib/keytab/ktadd.c /mit/krb5/src/lib/keytab/ktbase.c /mit/krb5/src/lib/keytab/ktdefault.c /mit/krb5/src/lib/keytab/ktfr_entry.c /mit/krb5/src/lib/keytab/ktremove.c /mit/krb5/src/lib/keytab/read_servi.c + +load /mit/krb5/src/lib/keytab/file/ktf_add.c /mit/krb5/src/lib/keytab/file/ktf_endget.c /mit/krb5/src/lib/keytab/file/ktf_next.c /mit/krb5/src/lib/keytab/file/ktf_resolv.c /mit/krb5/src/lib/keytab/file/ktf_wops.c /mit/krb5/src/lib/keytab/file/ktf_close.c /mit/krb5/src/lib/keytab/file/ktf_get_en.c /mit/krb5/src/lib/keytab/file/ktf_ops.c /mit/krb5/src/lib/keytab/file/ktf_ssget.c /mit/krb5/src/lib/keytab/file/ktf_wreslv.c /mit/krb5/src/lib/keytab/file/ktf_defops.c /mit/krb5/src/lib/keytab/file/ktf_get_na.c /mit/krb5/src/lib/keytab/file/ktf_remove.c /mit/krb5/src/lib/keytab/file/ktf_util.c + +load /mit/krb5/src/lib/ccache/ccbase.c /mit/krb5/src/lib/ccache/ccdefault.c /mit/krb5/src/lib/ccache/ccdefops.c + +load /mit/krb5/src/lib/ccache/file/fcc_close.c /mit/krb5/src/lib/ccache/file/fcc_destry.c /mit/krb5/src/lib/ccache/file/fcc_eseq.c /mit/krb5/src/lib/ccache/file/fcc_gennew.c /mit/krb5/src/lib/ccache/file/fcc_getnam.c /mit/krb5/src/lib/ccache/file/fcc_gprin.c /mit/krb5/src/lib/ccache/file/fcc_init.c /mit/krb5/src/lib/ccache/file/fcc_nseq.c /mit/krb5/src/lib/ccache/file/fcc_read.c /mit/krb5/src/lib/ccache/file/fcc_reslv.c /mit/krb5/src/lib/ccache/file/fcc_retrv.c /mit/krb5/src/lib/ccache/file/fcc_sseq.c /mit/krb5/src/lib/ccache/file/fcc_store.c /mit/krb5/src/lib/ccache/file/fcc_skip.c /mit/krb5/src/lib/ccache/file/fcc_ops.c /mit/krb5/src/lib/ccache/file/fcc_write.c /mit/krb5/src/lib/ccache/file/fcc_sflags.c /mit/krb5/src/lib/ccache/file/fcc_defops.c /mit/krb5/src/lib/ccache/file/fcc_errs.c /mit/krb5/src/lib/ccache/file/fcc_maybe.c + +load -I. -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES /mit/krb5/src/lib/rcache/rc_base.c /mit/krb5/src/lib/rcache/rc_dfl.c /mit/krb5/src/lib/rcache/rc_io.c /mit/krb5/src/lib/rcache/rcdef.c /mit/krb5/src/lib/rcache/rc_conv.c diff --git a/src/lib/krb5.saber.warnings b/src/lib/krb5.saber.warnings new file mode 100644 index 0000000..9fa9d2e --- /dev/null +++ b/src/lib/krb5.saber.warnings @@ -0,0 +1,294 @@ +---------------- +"/mit/krb5/src/lib/krb/gc_via_tgt.c":119, krb5_get_cred_via_tgt(), Statement not reached (Warning #529) + 118: return retval; + * 119: break; /* not strictly necessary... */ 120: } +( while sourcing "/tmp/saber.source":4 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/krb/in_tkt_sky.c":48, skey_keyproc(), Unused formal parameter (Warning #590) + 47: */ + * 48: static krb5_error_code + 49: skey_keyproc(DECLARG(const krb5_keytype, type), +( while sourcing "/tmp/saber.source":4 ) +Formal parameter 'padata' was not used. +---------------- +"/mit/krb5/src/lib/krb/rd_priv.c":63, krb5_rd_priv(), Unused formal parameter (Warning #590) + 62: + * 63: krb5_error_code + 64: krb5_rd_priv(DECLARG(const krb5_data *, inbuf), +( while sourcing "/tmp/saber.source":4 ) +Formal parameter 'recv_addr' was not used. +---------------- +"/usr/include/unistd.h":182, Function redeclared (Warning #701) + 181: + * 182: extern unsigned int + 183: alarm(), +( while sourcing "/tmp/saber.source":4 ) +Function 'alarm' was previously declared as: + extern int alarm(); +---------------- +"/usr/include/unistd.h":198, Function redeclared (Warning #701) + 197: + * 198: extern void + 199: _exit(); +( while sourcing "/tmp/saber.source":4 ) +Function '_exit' was previously declared as: + extern int _exit(); +---------------- +"/mit/krb5/src/lib/asn.1/kpwd2pwd.c":75, krb5_pwd_seq2KRB5_PWD__SEQ(), Functionredeclared (Warning #701) + 74: sizeof(struct type_KRB5_PasswdSequence))) == NULL) { + * 75: com_err("kpwd2pwd", 0, "Unable to Allocate PasswdSequence"); + 76: *error = ENOMEM; +( while sourcing "/tmp/saber.source":6 ) +Function 'com_err' was previously declared as: + extern void com_err(); +---------------- +"/mit/krb5/src/lib/keytab/file/ktf_util.c":601, krb5_ktfileint_size_entry(), Unused automatic variable (Warning #591) + 600: { + * 601: krb5_int16 count, size; + 602: krb5_int32 total_size, i; +( while sourcing "/tmp/saber.source":12 ) +Automatic variable 'size' was not used. +---------------- +"/mit/krb5/src/lib/keytab/file/ktf_util.c":757, krb5_ktfileint_find_slot(), Unused label (Warning #593) +( while sourcing "/tmp/saber.source":12 ) +Label 'abend' was not used. +---------------- +"/mit/krb5/src/lib/ccache/file/fcc_gennew.c":40, Unknown directive (Warning #471) + 39: #else + 40: #error find some way to use net-byte-order file version numbers. + ^ + 41: #endif +( while sourcing "/tmp/saber.source":16 ) +Directive 'error' is undefined. + +---------------- +"/mit/krb5/src/lib/ccache/file/fcc_gennew.c":77, krb5_fcc_generate_new(), Function redeclared (Warning #701) + 76: (void) strcat(scratch, "XXXXXX"); + * 77: mktemp(scratch); + 78: +( while sourcing "/tmp/saber.source":16 ) +Function 'mktemp' was previously declared as: + extern char *mktemp(); +---------------- +"/mit/krb5/src/lib/ccache/file/fcc_maybe.c":41, Unknown directive (Warning #471) + 40: #else + 41: #error find some way to use net-byte-order file version numbers. + ^ + 42: #endif +( while sourcing "/tmp/saber.source":16 ) +Directive 'error' is undefined. +Warning: 1 module currently not loaded. +Loading: -I. /mit/krb5/src/lib/rcache/rc_base.c + +---------------- +"/mit/krb5/src/lib/rcache/rc_base.h":13, Cannot read file (Error #400) + 12: #define KRB5_RC_H + * 13: #include <krb5/krb5.h> + 14: #include <krb5/ext-proto.h> +( while sourcing "/tmp/saber.source":18 ) +Cannot open 'krb5/krb5.h' for input. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":335, krb5_rc_dfl_recover(), Unused automatic variable (Warning #591) + 334: struct dfl_data *t = (struct dfl_data *)id->data; + * 335: int i; + 336: krb5_donot_replay *rep; +( while sourcing "/tmp/saber.source":18 ) +Automatic variable 'i' was not used. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":402, krb5_rc_dfl_recover(), Unused label (Warning #593) +( while sourcing "/tmp/saber.source":18 ) +Label 'end_loop' was not used. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":443, krb5_rc_dfl_store(), Statement not reached (Warning #529) + 442: case CMP_MALLOC: + * 443: return KRB5_RC_MALLOC; break; + 444: case CMP_REPLAY: +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":445, krb5_rc_dfl_store(), Statement not reached (Warning #529) + 444: case CMP_REPLAY: + * 445: return KRB5KRB_AP_ERR_REPEAT; break; + 446: case 0: break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":438, krb5_rc_dfl_store(), Unused automatic variable (Warning #591) + 437: struct dfl_data *t = (struct dfl_data *)id->data; + * 438: int i; + 439: +( while sourcing "/tmp/saber.source":18 ) +Automatic variable 'i' was not used. +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":525, krb5_rc_dfl_expunge(), Benign argumentmismatch (Warning #68) + 524: { + * 525: if (krb5_rc_io_store (&tmp, &q->rep)) + 526: return KRB5_RC_IO; +( while sourcing "/tmp/saber.source":18 ) +Benign type mismatch in call to function 'krb5_rc_io_store': +Argument #1 has type (struct krb5_rc_iostuff *) but type (struct dfl_data *) was expected. +Defined/declared in "/mit/krb5/src/lib/rcache/rc_dfl.c":404 +---------------- +"/mit/krb5/src/lib/rcache/rc_dfl.c":473, krb5_rc_dfl_expunge(), Unused automatic variable (Warning #591) + 472: struct dfl_data *t = (struct dfl_data *)id->data; + * 473: int i; + 474: #ifdef NOIOSTUFF +( while sourcing "/tmp/saber.source":18 ) +Automatic variable 'i' was not used. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":33, Unknown directive (Warning #471) + 32: #else + 33: #error find some way to use net-byte-order file version numbers. + ^ + 34: #endif +( while sourcing "/tmp/saber.source":18 ) +Directive 'error' is undefined. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":73, krb5_rc_io_creat(), Constant in conditional (Warning #558) + 72: + * 73: GETDIR; + 74: if (fn && *fn) +( while sourcing "/tmp/saber.source":18 ) +The conditional expression for 'do/while' is always false. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":156, krb5_rc_io_open(), Constant in conditional (Warning #558) + 155: + * 156: GETDIR; + 157: if (!(d->fn = malloc(strlen(fn) + dirlen + 1))) +( while sourcing "/tmp/saber.source":18 ) +The conditional expression for 'do/while' is always false. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":165, krb5_rc_io_open(), Function redeclared (Warning #701) + 164: + * 165: me = getuid(); + 166: /* must be owned by this user, to prevent some security problems with +( while sourcing "/tmp/saber.source":18 ) +Function 'getuid' was previously declared as: + extern short getuid(); +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":238, krb5_rc_io_write(), Statement not reached (Warning #529) + 237: { + * 238: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + 239: case EFBIG: return KRB5_RC_IO_SPACE; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":239, krb5_rc_io_write(), Statement not reached (Warning #529) + 238: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + * 239: case EFBIG: return KRB5_RC_IO_SPACE; break; + 240: #ifdef EDQUOT +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":241, krb5_rc_io_write(), Statement not reached (Warning #529) + 240: #ifdef EDQUOT + * 241: case EDQUOT: return KRB5_RC_IO_SPACE; break; + 242: #endif +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":243, krb5_rc_io_write(), Statement not reached (Warning #529) + 242: #endif + * 243: case ENOSPC: return KRB5_RC_IO_SPACE; break; + 244: case EIO: return KRB5_RC_IO_IO; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":244, krb5_rc_io_write(), Statement not reached (Warning #529) + 243: case ENOSPC: return KRB5_RC_IO_SPACE; break; + * 244: case EIO: return KRB5_RC_IO_IO; break; + 245: default: return KRB5_RC_IO_UNKNOWN; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":245, krb5_rc_io_write(), Statement not reached (Warning #529) + 244: case EIO: return KRB5_RC_IO_IO; break; + * 245: default: return KRB5_RC_IO_UNKNOWN; break; + 246: } +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":256, krb5_rc_io_sync(), Statement not reached (Warning #529) + 255: { + * 256: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + 257: case EIO: return KRB5_RC_IO_IO; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":257, krb5_rc_io_sync(), Statement not reached (Warning #529) + 256: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + * 257: case EIO: return KRB5_RC_IO_IO; break; + 258: default: return KRB5_RC_IO_UNKNOWN; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":258, krb5_rc_io_sync(), Statement not reached (Warning #529) + 257: case EIO: return KRB5_RC_IO_IO; break; + * 258: default: return KRB5_RC_IO_UNKNOWN; break; + 259: } +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":273, krb5_rc_io_read(), Statement not reached (Warning #529) + 272: { + * 273: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + 274: case EIO: return KRB5_RC_IO_IO; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":274, krb5_rc_io_read(), Statement not reached (Warning #529) + 273: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + * 274: case EIO: return KRB5_RC_IO_IO; break; + 275: default: return KRB5_RC_IO_UNKNOWN; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":275, krb5_rc_io_read(), Statement not reached (Warning #529) + 274: case EIO: return KRB5_RC_IO_IO; break; + * 275: default: return KRB5_RC_IO_UNKNOWN; break; + 276: } +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":298, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 297: { + * 298: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + 299: case EIO: return KRB5_RC_IO_IO; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":299, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 298: case EBADF: return KRB5_RC_IO_UNKNOWN; break; + * 299: case EIO: return KRB5_RC_IO_IO; break; + 300: case EPERM: return KRB5_RC_IO_PERM; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":300, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 299: case EIO: return KRB5_RC_IO_IO; break; + * 300: case EPERM: return KRB5_RC_IO_PERM; break; + 301: case EBUSY: return KRB5_RC_IO_PERM; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":301, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 300: case EPERM: return KRB5_RC_IO_PERM; break; + * 301: case EBUSY: return KRB5_RC_IO_PERM; break; + 302: case EROFS: return KRB5_RC_IO_PERM; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":302, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 301: case EBUSY: return KRB5_RC_IO_PERM; break; + * 302: case EROFS: return KRB5_RC_IO_PERM; break; + 303: default: return KRB5_RC_IO_UNKNOWN; break; +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. +---------------- +"/mit/krb5/src/lib/rcache/rc_io.c":303, krb5_rc_io_destroy(), Statement not reached (Warning #529) + 302: case EROFS: return KRB5_RC_IO_PERM; break; + * 303: default: return KRB5_RC_IO_UNKNOWN; break; + 304: } +( while sourcing "/tmp/saber.source":18 ) +The statement cannot be reached. diff --git a/src/lib/krb5/asn.1/.rconf b/src/lib/krb5/asn.1/.rconf new file mode 100644 index 0000000..abd9419 --- /dev/null +++ b/src/lib/krb5/asn.1/.rconf @@ -0,0 +1,8 @@ +ignore KRB5-types.c +ignore KRB5-types.h +ignore KRB5-types.py +ignore TAGS +ignore KRB5.ph +ignore Makefile.jtk +ignore glue2.c +ignore process.perl diff --git a/src/lib/krb5/asn.1/.saberinit b/src/lib/krb5/asn.1/.saberinit new file mode 100644 index 0000000..d14fddb --- /dev/null +++ b/src/lib/krb5/asn.1/.saberinit @@ -0,0 +1,4 @@ +alias hex print (unsigned) +setopt load_flags -I../include +load -lisode +alias reload load diff --git a/src/lib/krb5/asn.1/glue2.c b/src/lib/krb5/asn.1/glue2.c new file mode 100644 index 0000000..3267de1 --- /dev/null +++ b/src/lib/krb5/asn.1/glue2.c @@ -0,0 +1,31 @@ +#include <krb5/krb5.h> + +krb5_data string_list[3] = { +{14, "ATHENA.MIT.EDU"}, +{6, "jtkohl"}, +{4, "root"}, +}; + +krb5_data *princ[] = {&string_list[0], &string_list[1], &string_list[2], 0}; + +krb5_data string_list2[3] = { +{14, "ATHENA.MIT.EDU"}, +{6, "krbtgt"}, +{14, "ATHENA.MIT.EDU"}, +}; + +krb5_data *princ2[] = {&string_list2[0], &string_list2[1], &string_list2[2], 0}; + +krb5_last_req_entry lrentries[] = { {32000, 1}, {0, 3}, {10, 2} }; +krb5_last_req_entry *lrfoo1[] = {&lrentries[0], &lrentries[1], &lrentries[2], 0}; + +krb5_authdata adarr1[] = { {3, 7, "authdat"}, {2,4,"foob"}, {257,9,"jtkohlxxx"}}; +krb5_authdata *authdats[] = {&adarr1[0],&adarr1[1],&adarr1[2],0}; + +krb5_pa_data authdarr1[] = { {3, 7, "authdat"}, {2,4,"foob"}, {257,9,"jtkohlxxx"}}; +krb5_pa_data *padats[] = {&authdarr1[0],&authdarr1[1],&authdarr1[2],0}; + +krb5_address adrarr1[] = { {ADDRTYPE_INET,4,"abcd"}, + {ADDRTYPE_ISO,10,"6176432831"}, + {ADDRTYPE_INET,4,"efgh"} }; +krb5_address *addrs[] = {&adrarr1[0],&adrarr1[1],&adrarr1[2],0}; diff --git a/src/lib/krb5/asn.1/process.perl b/src/lib/krb5/asn.1/process.perl new file mode 100644 index 0000000..ce3e84b --- /dev/null +++ b/src/lib/krb5/asn.1/process.perl @@ -0,0 +1,50 @@ +# +# usage: perl process <input-c-file> <output-prefix> <c-flist> <o-flist> +# +$header = ""; +$count = 0; +$pepyid = ""; +$extrainclude = '#include <krb5/asn.1/KRB5-types-aux.h>' . "\n"; + +if ($#ARGV != 3) {die "Usage: process input-file.c output-prefix cflist-file oflist-file";} + +print "processing ", $ARGV[0], "\n"; +open(CFILE, "< $ARGV[0]") || die "can't open $ARGV[0]"; +open(CFLIST, "> $ARGV[2]") || die "can't open $ARGV[2]"; +open(OFLIST, "> $ARGV[3]") || die "can't open $ARGV[2]"; + +mainloop: while (<CFILE>) { + next mainloop if /^# line/; + if (/pepyid/) { + $pepyid = $_; + } elsif (/^\/\* ARGS|^free/) { + print "processing output from $pepyid" if ($count == 0); + close(OUTFILE); + $ofile = "$ARGV[1]" . $count . ".c"; + open(OUTFILE, ">$ofile" ) || die "can't open file $ofile"; + print OUTFILE $pepyid if ($count == 0); + print $ofile, "\n"; + @clist = (@clist, " " . $ofile); + $count++; + print OUTFILE $header; + print OUTFILE $extrainclude; + print OUTFILE $_; + } elsif ($count == 0) { + $header .= $_; + } else { + print OUTFILE $_; + } +} +close(OUTFILE); +print CFLIST "TYPESSRCS= ", @clist, "\n"; +close(CFLIST); +while ($cfile = shift(@clist)) { + $cfile =~ s/.c$/.o/; + @olist = (@olist, $cfile); +} +print OFLIST "TYPESOBJS=", @olist, "\n"; +close(OFLIST); +# +# $Source$ +# $Author$ +# $Id$ diff --git a/src/lib/krb5/ccache/file/.rconf b/src/lib/krb5/ccache/file/.rconf new file mode 100644 index 0000000..55ab262 --- /dev/null +++ b/src/lib/krb5/ccache/file/.rconf @@ -0,0 +1 @@ +ignore fcc_test.c diff --git a/src/lib/krb5/ccache/file/README b/src/lib/krb5/ccache/file/README new file mode 100644 index 0000000..e1aa6de --- /dev/null +++ b/src/lib/krb5/ccache/file/README @@ -0,0 +1,33 @@ +If OPENCLOSE is defined, ecah of the functions opens and closes the +file whenever it needs to access it. Otherwise, the file is opened +once in initialize and closed once is close. + +This library depends on UNIX-like file descriptors, and UNIX-like +behavior from the functions: open, close, read, write, lseek. + +The quasi-BNF grammar for a credentials cache: + +file ::= + principal list-of-credentials + +credential ::= + client (principal) + server (principal) + keyblock (keyblock) + times (ticket_times) + is_skey (boolean) + ticket_flags (flags) + ticket (data) + second_ticket (data) + +principal ::= + number of components (int32) + component 1 (data) + component 2 (data) + ... + +data ::= + length (int32) + string of length bytes + +etc. diff --git a/src/lib/krb5/ccache/file/todo b/src/lib/krb5/ccache/file/todo new file mode 100644 index 0000000..ed1ddb8 --- /dev/null +++ b/src/lib/krb5/ccache/file/todo @@ -0,0 +1,7 @@ +Make sure that each time a function returns KRB5_NOMEM, everything +allocated earlier in the function and stack tree is freed. + +File locking + +fcc_nseq.c and fcc_read don't check return values a lot. + diff --git a/src/lib/krb5/ccache/stdio/.rconf b/src/lib/krb5/ccache/stdio/.rconf new file mode 100644 index 0000000..874fb07 --- /dev/null +++ b/src/lib/krb5/ccache/stdio/.rconf @@ -0,0 +1 @@ +ignore x diff --git a/src/lib/krb5/ccache/stdio/README b/src/lib/krb5/ccache/stdio/README new file mode 100644 index 0000000..a986543 --- /dev/null +++ b/src/lib/krb5/ccache/stdio/README @@ -0,0 +1,39 @@ +If OPENCLOSE is defined, ecah of the functions opens and closes the +file whenever it needs to access it. Otherwise, the file is opened +once in initialize and closed once is close. + +This library depends on ANSI C library routines for file handling. It +may also have some implicit assumptions about UNIX, but we'll get +those out as much as possible. + +If you are running a UNIX system, you probably want to use the +UNIX-based "file" cache package instead of this. + +The quasi-BNF grammar for a credentials cache: + +file ::= + format-vno principal list-of-credentials + +credential ::= + client (principal) + server (principal) + keyblock (keyblock) + times (ticket_times) + is_skey (boolean) + ticket_flags (flags) + ticket (data) + second_ticket (data) + +principal ::= + number of components (int32) + component 1 (data) + component 2 (data) + ... + +data ::= + length (int32) + string of length bytes + +format-vno ::= <int16> + +etc. diff --git a/src/lib/krb5/ccache/stdio/todo b/src/lib/krb5/ccache/stdio/todo new file mode 100644 index 0000000..56a423f --- /dev/null +++ b/src/lib/krb5/ccache/stdio/todo @@ -0,0 +1,9 @@ +Make sure that each time a function returns KRB5_NOMEM, everything +allocated earlier in the function and stack tree is freed. + +Overwrite cache file with nulls before removing it. + +Check return values and sanity-check parameters more thoroughly. This +code was derived from UNIX file I/O code, and the conversion of +error-trapping may be incomplete. Probably lots of bugs dealing with +end-of-file versus other errors. diff --git a/src/lib/krb5/error_tables/.rconf b/src/lib/krb5/error_tables/.rconf new file mode 100644 index 0000000..9adf82b --- /dev/null +++ b/src/lib/krb5/error_tables/.rconf @@ -0,0 +1,4 @@ +ignore *.h +ignore *.c +ignore .rconf +link init_ets.c diff --git a/src/lib/krb5/rcache/.rconf b/src/lib/krb5/rcache/.rconf new file mode 100644 index 0000000..54e912b --- /dev/null +++ b/src/lib/krb5/rcache/.rconf @@ -0,0 +1,2 @@ +ignore README +ignore RELEASE diff --git a/src/lib/krb5/rcache/README b/src/lib/krb5/rcache/README new file mode 100644 index 0000000..99187cc --- /dev/null +++ b/src/lib/krb5/rcache/README @@ -0,0 +1,86 @@ +/* +Copyright 1990, Daniel J. Bernstein. All rights reserved. + +Please address any questions or comments to the author at brnstnd@acf10.nyu.edu. +*/ + +The #include's should be rewritten. + +All functions return 0 on success. + +Environment variables: KRB5RCACHETYPE, KRB5RCACHENAME, KRB5RCACHEDIR, +and TMPDIR. Obsolete: KRB5RCACHE. + +All header files are both ANSI-compatible and K&R-compatible. The .c files +are only ANSI compatible. Everything passes gcc -Wall -ansi -pedantic. + +Strings are freed using FREE(), which is defined in terms of free(). + +The error header files should be redone. + +The header files don't use __ because that's reserved. + +Each .c file assumes <malloc.h>. rc_io.c assumes fsync() and a gaggle of +error codes. These assumptions are not as portable as the code itself. + + +rcache.c: + +The rcache.c compatibility interface's type registration is a no-op; it +simply passes the type name on to rc_base.h. rcache.h is obsolete; use +rc_base.h if possible. + +There are some slight differences between rcache.c and the prototypes I +saw in krb/func-proto.h. Don't look at me, it's your interface. + +rcache.c's get_name doesn't fill with zeros unless strncpy does. + + +rc_base.c: + +If SEMAPHORE is defined and <semaphore.h> exists when rc_base.c is +compiled, all access to the type list will be protected by appropriate +semaphore ups and downs. This is untested. + +It doesn't take linker magic to preregister types. Just change the +typehead initialization in rc_base.c, with an appropriate include file +setting the ops. + + +rc_dfl.c: + +If NOIOSTUFF is defined when rc_dfl.c is compiled, all dfl rcaches will +be per-process. This is untested. + +Provided that separate threads use separate rcaches, rc_dfl.c is safe +for multithreading. + +Getting the name of a cache is only valid after it is created and before +it is closed. Recovering a cache is only valid after it has been created. + +krb5_unparse_name had better produce a zero-terminated string. + +rc_dfl.c isn't smart enough to try expunge/retry upon a malloc error. +Then again, such an error indicates that the whole system's about to die; +without real memory management there's no good solution. + +HASHSIZE can be defined at compile time. It defaults to 997 in rc_dfl.c. +EXCESSREPS can be defined at compile time. It defaults to 30 in rc_dfl.c. + +Hopefully adding a deltat to a time to compare to another time cannot +overflow. + +In rc_dfl's struct dfl_data, the name field is never freed, even though +it may be malloced by io_creat on a generate-name call. This should not +be a problem: a single process should not be opening and closing many +rcaches. One fix would be another field to indicate whether the string +was malloced or not; normally this is an unstated characteristic of a +char pointer, but here it would have to be explicit. + + +rc_io.c: + +rc_io.c assumes that siginterrupt() is not set. If siginterrupt() is set +and a signal occurs during, say, close(), then the close will fail. + +On a machine without fsync() you might as well not use the disk at all. diff --git a/src/lib/krb5/rcache/RELEASE b/src/lib/krb5/rcache/RELEASE new file mode 100644 index 0000000..21a4624 --- /dev/null +++ b/src/lib/krb5/rcache/RELEASE @@ -0,0 +1,17 @@ +Text of Mr. Bernstein's release: + +"I" henceforth refers to Daniel J. Bernstein. + +"rcshar" henceforth refers to the attached document, as sent from Daniel +J. Bernstein to Project Athena on 11 March 1990 + +I am the author of and sole copyright holder upon rcshar. + +I hereby waive copyright upon rcshar. rcshar is hereby public domain. + +I hereby also waive copyright upon any works that are (1) derived from +rcshar and (2) prepared between 11 March 1990 and 1 January 1991. + +Daniel J. Bernstein + +<signature>, dated 7 July 1990 |