/** * shishi_keys_print: * @keys: key set to print. * @fh: file handle, open for writing, to print keys to. * * Print all keys in set using shishi_key_print. * * Returns: Returns %SHISHI_OK on success. **/ int shishi_keys_print (Shishi_keys * keys, FILE *fh) { int rc; int i; for (i = 0; i < keys->nkeys; i++) { rc = shishi_key_print (keys->handle, fh, shishi_keys_nth (keys, i)); if (rc != SHISHI_OK) return rc; fprintf (fh, "\n"); } return SHISHI_OK; }
/** * shishi_keys_for_serverrealm_in_file * @handle: Shishi library handle create by shishi_init(). * @filename: file to read keys from. * @server: server name to get key for. * @realm: realm of server to get key for. * * Get keys that match specified @server and @realm from the key set * file @filename. * * Return value: Returns the key for specific server and realm, read * from the indicated file, or NULL if no key could be found or an * error encountered. **/ Shishi_key * shishi_keys_for_serverrealm_in_file (Shishi * handle, const char *filename, const char *server, const char *realm) { Shishi_key *key = NULL; FILE *fh; int res; fh = fopen (filename, "r"); if (fh == NULL) return NULL; res = SHISHI_OK; while (!feof (fh)) { res = shishi_key_parse (handle, fh, &key); if (res != SHISHI_OK || key == NULL) break; if (VERBOSENOISE (handle)) { printf ("Read key:\n"); shishi_key_print (handle, stdout, key); } if ((!server || (shishi_key_principal (key) && strcmp (server, shishi_key_principal (key)) == 0)) && (!realm || (shishi_key_realm (key) && strcmp (realm, shishi_key_realm (key)) == 0))) break; shishi_key_done (key); key = NULL; } res = fclose (fh); if (res != 0) return NULL; return key; }
/** * shishi_keys_add_keytab_mem: * @handle: shishi handle as allocated by shishi_init(). * @data: constant memory buffer with keytab of @len size. * @len: size of memory buffer with keytab data. * @keys: allocated key set to store keys in. * * Read keys from a MIT keytab data structure, and add them to the key * set. * * The format of keytab's is proprietary, and this function support * the 0x0501 and 0x0502 formats. See the section The MIT Kerberos * Keytab Binary File Format in the Shishi manual for a description of * the reverse-engineered format. * * Returns: Returns %SHISHI_KEYTAB_ERROR if the data does not * represent a valid keytab structure, and %SHISHI_OK on success. **/ int shishi_keys_add_keytab_mem (Shishi * handle, const char *data, size_t len, Shishi_keys *keys) { int rc; uint16_t file_format_version; size_t entrystartpos; uint16_t num_components; /* sub 1 if version 0x501 */ size_t i; Shishi_key *key; if (VERBOSENOISE (handle)) { printf ("keytab len %d (0x%x)\n", len, len); _shishi_hexprint (data, len); } /* Check file format. */ file_format_version = (data[0] << 8) | data[1]; if (VERBOSENOISE (handle)) printf ("keytab file_format_version %04X\n", file_format_version); if (file_format_version != 0x0501 && file_format_version != 0x0502) return SHISHI_KEYTAB_ERROR; /* Check file integrity first, to avoid error-checking below. */ entrystartpos = 2; while (entrystartpos < len) { int32_t size = data[entrystartpos] << 24 | data[entrystartpos+1] << 16 | data[entrystartpos+2] << 8 | data[entrystartpos+3]; entrystartpos += 4; if (VERBOSENOISE (handle)) { printf ("keytab size %d (%x)\n", size, size); printf ("keytab pos %d < %d\n", entrystartpos + size, len); } if (entrystartpos + size > len) return SHISHI_KEYTAB_ERROR; /* Go to next entry... */ entrystartpos += size; } if (entrystartpos != len) return SHISHI_KEYTAB_ERROR; rc = shishi_key (handle, &key); if (rc != SHISHI_OK) return rc; entrystartpos = 2; while (entrystartpos < len) { size_t pos = entrystartpos; uint16_t size = data[pos] << 24 | data[pos+1] << 16 | data[pos+2] << 8 | data[pos+3]; pos += 4; if (VERBOSENOISE (handle)) printf ("keytab size %d (%x)\n", size, size); /* Num_components */ num_components = data[pos] << 8 | data[pos+1]; pos += 2; if (file_format_version == 0x0501) num_components--; /* Realm */ { uint16_t realmlen = data[pos] << 8 | data[pos+1]; char *realm = xstrndup (&data[pos + 2], realmlen);; pos += 2 + realmlen; shishi_key_realm_set (key, realm); free (realm); } /* Principal components. */ { char *name = NULL; size_t namelen = 0; for (i = 0; i < num_components; i++) { size_t l; l = data[pos] << 8 | data[pos+1]; pos += 2; name = xrealloc (name, namelen + l + 1); memcpy (name + namelen, &data[pos], l); name[namelen + l] = '/'; namelen += l + 1; pos += l; } name[namelen - 1] = '\0'; shishi_key_principal_set (key, name); free (name); } /* Name_type */ { uint32_t name_type /* not present if version 0x501 */ = data[pos] << 24 | data[pos+1] << 16 | data[pos+2] << 8 | data[pos+3]; pos += 4; if (VERBOSENOISE (handle)) printf ("keytab nametype %d (0x%08x)\n", name_type, name_type); } /* Timestamp */ { uint32_t timestamp = data[pos] << 24 | data[pos+1] << 16 | data[pos+2] << 8 | data[pos+3]; pos += 4; if (VERBOSENOISE (handle)) printf ("keytab timestamp %u (0x%08ux)\n", timestamp, timestamp); } /* keyvno8 */ { uint8_t vno8 = data[pos++]; if (VERBOSENOISE (handle)) printf ("keytab kvno8 %d (0x%02x)\n", vno8, vno8); shishi_key_version_set (key, vno8); } /* key, keytype */ { uint32_t keytype = data[pos] << 8 | data[pos+1]; pos += 2; if (VERBOSENOISE (handle)) printf ("keytab keytype %d (0x%x)\n", keytype, keytype); shishi_key_type_set (key, keytype); } /* key, length and data */ { uint16_t keylen = data[pos] << 8 | data[pos+1]; pos += 2; if (VERBOSENOISE (handle)) printf ("keytab keylen %d (0x%x) eq? %d\n", keylen, keylen, shishi_key_length (key)); if (VERBOSENOISE (handle)) _shishi_hexprint (data + pos, keylen); shishi_key_value_set (key, data + pos); pos += keylen; } if (pos - entrystartpos < (size_t) size + 4) { uint32_t vno /* only present if >= 4 bytes left in entry */ = data[pos] << 24 | data[pos+1] << 16 | data[pos+2] << 8 | data[pos+3]; pos += 4; if (VERBOSENOISE (handle)) printf ("keytab kvno %d (0x%08x)\n", vno, vno); shishi_key_version_set (key, vno); } if (VERBOSECRYPTONOISE (handle)) shishi_key_print (handle, stdout, key); rc = shishi_keys_add (keys, key); if (rc != SHISHI_OK) goto done; /* Go to next entry... */ entrystartpos += size + 4; } rc = SHISHI_OK; done: shishi_key_done (key); return rc; }
static Shishi_ap * auth (Shishi * h, int verbose, const char *cname, const char *sname) { Shishi_key *key; Shishi_ap *ap; Shishi_asn1 apreq; char *buf; size_t buflen; int rc; printf ("Client: %s\n", cname); printf ("Server: %s\n", sname); /* Get key for the server. */ key = shishi_hostkeys_for_server (h, sname); if (!key) { printf ("could not find key: %s\n", shishi_error (h)); return NULL; } if (verbose) shishi_key_print (h, stderr, key); /* Read Authentication request from client */ printf ("Waiting for client to authenticate itself...\n"); rc = shishi_apreq_parse (h, stdin, &apreq); if (rc != SHISHI_OK) { printf ("could not read AP-REQ: %s\n", shishi_strerror (rc)); return NULL; } /* Create Authentication context */ rc = shishi_ap (h, &ap); if (rc != SHISHI_OK) { printf ("Could not create AP: %s\n", shishi_strerror (rc)); return NULL; } /* Store request in context */ shishi_ap_req_set (ap, apreq); /* Process authentication request */ rc = shishi_ap_req_process (ap, key); if (rc != SHISHI_OK) { printf ("Could not process AP-REQ: %s\n", shishi_strerror (rc)); return NULL; } if (verbose) shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap)); rc = shishi_authenticator_client (h, shishi_ap_authenticator (ap), &buf, &buflen); printf ("Client name (from authenticator): %.*s\n", (int) buflen, buf); free (buf); rc = shishi_encticketpart_clientrealm (h, shishi_tkt_encticketpart (shishi_ap_tkt (ap)), &buf, &buflen); printf ("Client name (from encticketpart): %.*s\n", (int) buflen, buf); free (buf); rc = shishi_ticket_server (h, shishi_tkt_ticket (shishi_ap_tkt (ap)), &buf, &buflen); printf ("Server name (from ticket): %.*s\n", (int) buflen, buf); free (buf); /* User is authenticated. */ printf ("User authenticated.\n"); /* Authenticate ourself to client, if request */ if (shishi_apreq_mutual_required_p (h, apreq)) { Shishi_asn1 aprep; printf ("Mutual authentication required.\n"); rc = shishi_ap_rep_asn1 (ap, &aprep); if (rc != SHISHI_OK) { printf ("Error creating AP-REP: %s\n", shishi_strerror (rc)); return NULL; } if (verbose) shishi_encapreppart_print (h, stderr, shishi_ap_encapreppart (ap)); shishi_aprep_print (h, stdout, aprep); /* We are authenticated to client */ } return ap; }