-
-/* Verifies received public key. If user decides to trust the key it is
- saved as trusted server key for later use. If user does not trust the
- key this returns FALSE. */
-
-int silc_client_verify_server_key(SilcClient client,
- SilcSocketConnection sock,
- unsigned char *pk, unsigned int pk_len,
- SilcSKEPKType pk_type)
-{
- char filename[256];
- char file[256];
- char *hostname, *fingerprint;
- struct passwd *pw;
- struct stat st;
-
- hostname = sock->hostname ? sock->hostname : sock->ip;
-
- if (pk_type != SILC_SKE_PK_TYPE_SILC) {
- silc_say(client, "We don't support server %s key type", hostname);
- return FALSE;
- }
-
- pw = getpwuid(getuid());
- if (!pw)
- return FALSE;
-
- memset(filename, 0, sizeof(filename));
- memset(file, 0, sizeof(file));
- snprintf(file, sizeof(file) - 1, "serverkey_%s_%d.pub", hostname,
- sock->port);
- snprintf(filename, sizeof(filename) - 1, "%s/.silc/serverkeys/%s",
- pw->pw_dir, file);
-
- /* Check wheter this key already exists */
- if (stat(filename, &st) < 0) {
-
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);
- silc_free(fingerprint);
-
- /* Ask user to verify the key and save it */
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key (y/n)? "))
- {
- /* Save the key for future checking */
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
- } else {
- /* The key already exists, verify it. */
- SilcPublicKey public_key;
- unsigned char *encpk;
- unsigned int encpk_len;
-
- /* Load the key file */
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_PEM))
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_BIN)) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);
- silc_free(fingerprint);
- silc_say(client, "Could not load your local copy of the server %s key",
- hostname);
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
- return FALSE;
- }
-
- /* Encode the key data */
- encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
- if (!encpk) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);
- silc_free(fingerprint);
- silc_say(client, "Your local copy of the server %s key is malformed",
- hostname);
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
- return FALSE;
- }
-
- if (memcmp(encpk, pk, encpk_len)) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);
- silc_free(fingerprint);
- silc_say(client, "Server %s key does not match with your local copy",
- hostname);
- silc_say(client, "It is possible that the key has expired or changed");
- silc_say(client, "It is also possible that some one is performing "
- "man-in-the-middle attack");
-
- /* Ask user to verify the key and save it */
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
- silc_say(client, "Will not accept server %s key", hostname);
- return FALSE;
- }
-
- /* Local copy matched */
- return TRUE;
- }
-
- silc_say(client, "Will not accept server %s key", hostname);
- return FALSE;
-}
-
-
-/* Parse nickname string. The format may be <num>!<nickname>@<server> to
- support multiple same nicknames. The <num> is the final unifier if same
- nickname is on same server. Note, this is only local format and server
- does not know anything about these. */
-
-int silc_client_parse_nickname(char *string, char **nickname, char **server,
- unsigned int *num)
-{
- unsigned int tlen;
- char tmp[256];
-
- if (!string)
- return FALSE;
-
- if (strchr(string, '!')) {
- tlen = strcspn(string, "!");
- memset(tmp, 0, sizeof(tmp));
- memcpy(tmp, string, tlen);
-
- if (num)
- *num = atoi(tmp);
-
- if (tlen >= strlen(string))
- return FALSE;
-
- string += tlen + 1;
- }
-
- if (strchr(string, '@')) {
- tlen = strcspn(string, "@");
-
- if (nickname) {
- *nickname = silc_calloc(tlen + 1, sizeof(char));
- memcpy(*nickname, string, tlen);
- }
-
- if (server) {
- *server = silc_calloc(strlen(string) - tlen, sizeof(char));
- memcpy(*server, string + tlen + 1, strlen(string) - tlen - 1);
- }
- } else {
- if (nickname)
- *nickname = strdup(string);
- }
-
- return TRUE;
-}