From b3e67d3dfa6409755be33f352b5a86fbb094a570 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Fri, 5 Apr 2002 17:36:12 +0000 Subject: [PATCH] updates. --- CHANGES | 8 + TODO | 5 - apps/irssi/src/silc/core/client_ops.c | 2 +- apps/irssi/src/silc/core/silc-servers.c | 2 +- apps/silcd/command.c | 8 +- apps/silcd/packet_receive.c | 2 +- apps/silcd/protocol.c | 6 +- apps/silcd/serverconfig.c | 20 ++- doc/draft-riikonen-silc-commands-03.nroff | 11 +- doc/draft-riikonen-silc-ke-auth-05.nroff | 15 +- doc/draft-riikonen-silc-pp-05.nroff | 17 ++- doc/draft-riikonen-silc-spec-05.nroff | 31 ++-- includes/silcincludes.h | 1 + lib/silcclient/client.c | 20 ++- lib/silcclient/client_ftp.c | 2 +- lib/silcclient/client_internal.h | 3 + lib/silcclient/client_ops_example.c | 3 +- lib/silcclient/command.c | 2 +- lib/silcclient/protocol.c | 13 ++ lib/silcclient/silcclient.h | 9 +- lib/silccore/silcauth.c | 23 ++- lib/silccore/silcauth.h | 24 +-- lib/silccrypt/silcpkcs.c | 8 +- lib/silcutil/DIRECTORY | 1 + lib/silcutil/Makefile.am | 2 + lib/silcutil/silcstrutil.c | 1 + lib/silcutil/silcstrutil.h | 176 ++++++++++++++++++++++ lib/silcutil/silcutil.c | 151 ------------------- lib/silcutil/silcutil.h | 46 +----- 29 files changed, 335 insertions(+), 277 deletions(-) create mode 100644 lib/silcutil/silcstrutil.h diff --git a/CHANGES b/CHANGES index da17f33e..fc475d70 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,14 @@ Fri Apr 5 16:03:03 EEST 2002 Pekka Riikonen lib/silcclient/protocol.c, silcd/protocol.c, silcd/serverconfig.c, and lib/silccore/silcauth.c. + * Changed the silc_client_close_connection interface to not + need the SilcSocketConnection which should not be visible + to application. Affected files are lib/silcclient/client.c + and lib/silcclient/silcclient.h. + + * Rewrote the text for Private Message Key Payload in the + protocol specification. Protocol TODO #11. + Wed Apr 3 16:24:51 EEST 2002 Pekka Riikonen * Upgraded the protocol version to 1.1, updated protocol specs diff --git a/TODO b/TODO index 2f49dc64..17012127 100644 --- a/TODO +++ b/TODO @@ -145,11 +145,6 @@ describe new stuff to be added to protocol versions 1.x. payload MAC and not alone by packet MAC. To be included in protocol version 1.1. - 11. Change the wording in Private Message Key Payload definition to - describe the problems of trusting the payload, and to indicate that - the receiver may not accept the key in the payload, and to describe - other means of distributing a key. - 16. Add STATS command after all to the protocol for providing practically same information client gets when connects to a server. Normal server would send this to router always when received from client. diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index a4008b78..b76c467d 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -601,7 +601,7 @@ void silc_connect(SilcClient client, SilcClientConnection conn, int success) SILC_SERVER_REC *server = conn->context; if (!server && !success) { - silc_client_close_connection(client, NULL, conn); + silc_client_close_connection(client, conn); return; } diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 7c3a6918..f24ba508 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -221,7 +221,7 @@ static void sig_disconnected(SILC_SERVER_REC *server) silc_dlist_uninit(server->ftp_sessions); if (server->conn && server->conn->sock != NULL) { - silc_client_close_connection(silc_client, NULL, server->conn); + silc_client_close_connection(silc_client, server->conn); /* SILC closes the handle */ g_io_channel_unref(net_sendbuffer_handle(server->handle)); diff --git a/apps/silcd/command.c b/apps/silcd/command.c index ba345af6..98f1a29c 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -3825,15 +3825,13 @@ SILC_SERVER_CMD_FUNC(cmode) } /* Save the passphrase */ - passphrase = channel->passphrase = strdup(tmp); + passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp)); } } else { if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) { /* Passphrase mode is unset. remove the passphrase */ - if (channel->passphrase) { - silc_free(channel->passphrase); - channel->passphrase = NULL; - } + silc_free(channel->passphrase); + channel->passphrase = NULL; } } diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index f0c3616d..56f01569 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -595,7 +595,7 @@ void silc_server_notify(SilcServer server, tmp = silc_argument_get_arg_type(args, 5, &tmp_len); if (tmp) { silc_free(channel->passphrase); - channel->passphrase = strdup(tmp); + channel->passphrase = silc_memdup(tmp, tmp_len); } break; diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index eb7b3013..6aa3ac93 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -690,10 +690,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange) */ static int -silc_server_password_authentication(SilcServer server, char *remote_auth, - char *local_auth) +silc_server_password_authentication(SilcServer server, char *local_auth, + char *remote_auth) { - if (!remote_auth || !local_auth) + if (!remote_auth || !local_auth || strlen(local_auth) != strlen(remote_auth)) return FALSE; if (!memcmp(remote_auth, local_auth, strlen(local_auth))) diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index b5dbc04c..cd5a0d37 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -113,18 +113,26 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p, { if (auth_meth == SILC_AUTH_PASSWORD) { /* p is a plain text password */ - if (auth_data) - *auth_data = (void *) strdup(p); - if (auth_data_len) - *auth_data_len = (SilcUInt32) strlen(p); + if (auth_data && auth_data_len) { + if (!silc_utf8_valid(p, strlen(p))) { + *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0); + *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char)); + silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data, + *auth_data_len); + } else { + *auth_data = (void *) strdup(p); + *auth_data_len = (SilcUInt32) strlen(p); + } + } } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) { /* p is a public key file name */ SilcPublicKey public_key; if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM)) if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) { - SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: " - "Could not load public key file!\n", line)); + SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line " + "%lu: Could not load public key file!\n", + line)); return FALSE; } diff --git a/doc/draft-riikonen-silc-commands-03.nroff b/doc/draft-riikonen-silc-commands-03.nroff index d0dcd698..b5d03877 100644 --- a/doc/draft-riikonen-silc-commands-03.nroff +++ b/doc/draft-riikonen-silc-commands-03.nroff @@ -202,7 +202,9 @@ are defined in the section 2.3 SILC Command Status Types. Every command that has some kind of ID as argument (for example ) are actually ID Payloads, defined in [SILC2] that includes the type of the ID, length of the ID and the actual ID data. This -way variable length ID's can be sent as arguments. +way variable length ID's can be sent as arguments. Also note that +all passphrases that may be sent in commands MUST be UTF-8 [RFC2279] +encoded. .ti 0 @@ -603,8 +605,7 @@ List of all defined commands in SILC follows. (3) [] This command replies with the invite list of the channel if it - exists. The may be omitted if the list was not - altered. + exists. Status messages: @@ -1896,8 +1897,8 @@ security of this protocol. [RFC2119] Bradner, S., "Key Words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. - - +[RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO + 10646", RFC 2279, January 1998. diff --git a/doc/draft-riikonen-silc-ke-auth-05.nroff b/doc/draft-riikonen-silc-ke-auth-05.nroff index 4e207e4f..495647ba 100644 --- a/doc/draft-riikonen-silc-ke-auth-05.nroff +++ b/doc/draft-riikonen-silc-ke-auth-05.nroff @@ -200,7 +200,9 @@ whether it supports the security properties. It then sends a Key Exchange Start Payload to the initiator filled with security properties it selected from the original payload. The payload -sent by responder MUST include only one chosen property per list. +sent by responder MUST include only one chosen property per list. The +character encoding for the security property values as defined in [SILC1] +SHOULD be UTF-8 [RFC2279]. The Key Exchange Start Payload is used to tell connecting entities what security properties and algorithms should be used in the communication. @@ -958,7 +960,13 @@ for defined numerical authentication method types. Passphrase authentication or pre-shared-key based authentication is simply an authentication where the party that wants to authenticate itself to the other end sends the passphrase that is required by -the other end, for example server. +the other end, for example server. The plaintext passphrase is put +to the payload, that is then encrypted. The plaintext passphrase +MUST be in UTF-8 [RFC2279] encoding. If the passphrase is in the +sender's system in some other encoding it MUST be UTF-8 encoded +before transmitted. The receiver MAY change the encoding of the +passphrase to its system's default character encoding before verifying +the passphrase. If the passphrase matches with the one in the server's end the authentication is successful. Otherwise SILC_PACKET_FAILURE MUST be @@ -1101,6 +1109,9 @@ security of this protocol. [RFC2119] Bradner, S., "Key Words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. +[RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO + 10646", RFC 2279, January 1998. + .ti 0 6 Author's Address diff --git a/doc/draft-riikonen-silc-pp-05.nroff b/doc/draft-riikonen-silc-pp-05.nroff index 36dee34b..9c8a5cc6 100644 --- a/doc/draft-riikonen-silc-pp-05.nroff +++ b/doc/draft-riikonen-silc-pp-05.nroff @@ -1839,11 +1839,18 @@ o Padding (variable length) - This field is present only .ti 0 2.3.12 Private Message Key Payload -This payload is used to send key from client to another client that -is going to be used to protect the private messages between these -two clients. If this payload is not sent normal session key -established by the SILC Key Exchange Protocol is used to protect -the private messages. +This payload is optional and can be used to send private message +key between two clients in the network. The packet is secured with +normal session keys. By default private messages are encrypted +with session keys, and with this payload it is possible to set +private key for private message encryption between two clients. + +The receiver of this payload SHOULD verify for example from user +whether user wants to receive private message key. Note that there +are other, more secure ways of exchanging private message keys in +the SILC network. Instead of sending this payload it is possible to +negotiate the private message key with SKE protocol using the Key +Agreement payload directly peer to peer. This payload may only be sent by client to another client. Server MUST NOT send this payload at any time. After sending this payload diff --git a/doc/draft-riikonen-silc-spec-05.nroff b/doc/draft-riikonen-silc-spec-05.nroff index 1841178d..72369b8d 100644 --- a/doc/draft-riikonen-silc-spec-05.nroff +++ b/doc/draft-riikonen-silc-spec-05.nroff @@ -1047,8 +1047,9 @@ completed. The purpose of authentication is to authenticate for example client connecting to the server. However, usually clients are accepted to connect to server without explicit authentication. Servers are required use authentication protocol when connecting. The authentication -may be based on passphrase (pre-shared-secret) or public key. The -connection authentication protocol is described in detail in [SILC3]. +may be based on passphrase (pre-shared-secret) or public key. All +passphrases sent in SILC protocol MUST be UTF-8 [RFC2279] encoded. +The connection authentication protocol is described in detail in [SILC3]. .ti 0 @@ -1118,9 +1119,9 @@ o Authentication Data (variable length) - Authentication If the authentication method is password based, the Authentication -Data field includes the plaintext password. It is safe to send -plaintext password since the entire payload is encrypted. In this -case the Public Data Length is set to zero (0), but MAY also include +Data field includes the plaintext UTF-8 encoded password. It is safe +to send plaintext password since the entire payload is encrypted. In +this case the Public Data Length is set to zero (0), but MAY also include random data for padding purposes. It is also RECOMMENDED that maximum amount of padding is applied to SILC packet when using password based authentication. This way it is not possible to approximate the length @@ -1421,14 +1422,15 @@ software version = [.[.]] .in 3 Protocol version MAY provide both major and minor version. Currently -implementations MUST set the protocol version and accept the protocol -version as SILC-1.1-. If new protocol version causes -in compatibilities with older version the the versio number MUST -be incremented. The is incremented if new protocol version is -fully incompatible. +implementations MUST set the protocol version and accept at least the +protocol version as SILC-1.1-. If new protocol version +causes in compatibilities with older version the the versio number +MUST be incremented. The is incremented if new protocol version +is fully incompatible. -Software version MAY provide major, minor and build version. The -software version MAY be freely set and accepted. +Software version MAY provide major, minor and build (vendor) version. +The software version MAY be freely set and accepted. The version string +MUST consist of printable US-ASCII characters. Thus, the version strings could be, for example: @@ -1437,6 +1439,7 @@ Thus, the version strings could be, for example: SILC-1.1-2.0.2 SILC-1.0-1.2 SILC-1.1-1.0.VendorXYZ +SILC-1.1-2.4.5 Vendor Limited .in 3 @@ -2220,8 +2223,8 @@ should have a forum to discuss the cell management issues. [RFC2119] Bradner, S., "Key Words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. - - +[RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO + 10646", RFC 2279, January 1998. diff --git a/includes/silcincludes.h b/includes/silcincludes.h index 0c72f406..a74228dc 100644 --- a/includes/silcincludes.h +++ b/includes/silcincludes.h @@ -230,6 +230,7 @@ extern "C" { #include "silcbuffmt.h" #include "silcnet.h" #include "silcfileutil.h" +#include "silcstrutil.h" #include "silcutil.h" #include "silcconfig.h" #include "silcprotocol.h" diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 64ecee88..4875e8e2 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -806,14 +806,14 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process) if (SILC_IS_DISCONNECTING(sock)) { if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) client->internal->ops->disconnect(client, conn); - silc_client_close_connection(client, sock, conn); + silc_client_close_connection_real(client, sock, conn); return; } SILC_LOG_DEBUG(("EOF from connection %d", sock->sock)); if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) client->internal->ops->disconnect(client, conn); - silc_client_close_connection(client, sock, conn); + silc_client_close_connection_real(client, sock, conn); return; } @@ -1278,9 +1278,9 @@ void silc_client_packet_queue_purge(SilcClient client, connection but `conn->sock' might be actually a different connection than the `sock'). */ -void silc_client_close_connection(SilcClient client, - SilcSocketConnection sock, - SilcClientConnection conn) +void silc_client_close_connection_real(SilcClient client, + SilcSocketConnection sock, + SilcClientConnection conn) { int del = FALSE; @@ -1395,6 +1395,14 @@ void silc_client_close_connection(SilcClient client, silc_socket_free(sock); } +/* Closes the connection to the remote end */ + +void silc_client_close_connection(SilcClient client, + SilcClientConnection conn) +{ + silc_client_close_connection_real(client, NULL, conn); +} + /* Called when we receive disconnection packet from server. This closes our end properly and displays the reason of the disconnection on the screen. */ @@ -1408,7 +1416,7 @@ SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later) if (sock == NULL) return; - silc_client_close_connection(client, sock, sock->user_data); + silc_client_close_connection_real(client, sock, sock->user_data); } /* Called when we receive disconnection packet from server. This diff --git a/lib/silcclient/client_ftp.c b/lib/silcclient/client_ftp.c index a6726709..6d63544d 100644 --- a/lib/silcclient/client_ftp.c +++ b/lib/silcclient/client_ftp.c @@ -754,7 +754,7 @@ void silc_client_ftp_session_free(SilcClientFtpSession session) if (conn->active_session == session) conn->active_session = NULL; - silc_client_close_connection(session->client, session->sock, conn); + silc_client_close_connection_real(session->client, session->sock, conn); } else { silc_socket_free(session->sock); } diff --git a/lib/silcclient/client_internal.h b/lib/silcclient/client_internal.h index 294e003a..7de59e7f 100644 --- a/lib/silcclient/client_internal.h +++ b/lib/silcclient/client_internal.h @@ -155,6 +155,9 @@ void silc_client_packet_send(SilcClient client, unsigned char *data, SilcUInt32 data_len, int force_send); +void silc_client_close_connection_real(SilcClient client, + SilcSocketConnection sock, + SilcClientConnection conn); void silc_client_disconnected_by_server(SilcClient client, SilcSocketConnection sock, SilcBuffer message); diff --git a/lib/silcclient/client_ops_example.c b/lib/silcclient/client_ops_example.c index 7ecb981b..e35a56e6 100644 --- a/lib/silcclient/client_ops_example.c +++ b/lib/silcclient/client_ops_example.c @@ -164,7 +164,8 @@ silc_verify_public_key(SilcClient client, SilcClientConnection conn, /* Ask (interact, that is) a passphrase from user. The passphrase is returned to the library by calling the `completion' callback with - the `context'. */ + the `context'. The returned passphrase SHOULD be in UTF-8 encoded, + if not then the library will attempt to encode. */ static void silc_ask_passphrase(SilcClient client, SilcClientConnection conn, diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index f6813f34..48b7cd27 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -663,7 +663,7 @@ SILC_TASK_CALLBACK(silc_client_command_quit_cb) /* Close connection */ q->client->internal->ops->disconnect(q->client, q->conn); - silc_client_close_connection(q->client, NULL, q->conn->sock->user_data); + silc_client_close_connection(q->client, q->conn->sock->user_data); silc_free(q); } diff --git a/lib/silcclient/protocol.c b/lib/silcclient/protocol.c index 3c66d905..6ab25d68 100644 --- a/lib/silcclient/protocol.c +++ b/lib/silcclient/protocol.c @@ -572,9 +572,21 @@ silc_client_conn_auth_continue(unsigned char *auth_data, SilcClient client = (SilcClient)ctx->client; SilcBuffer packet; int payload_len = 0; + unsigned char *autf8 = NULL; SILC_LOG_DEBUG(("Start")); + /* Passphrase must be UTF-8 encoded, if it isn't encode it */ + if (ctx->auth_meth == SILC_AUTH_PASSWORD && + !silc_utf8_valid(auth_data, auth_data_len)) { + payload_len = silc_utf8_encoded_len(auth_data, auth_data_len, + SILC_STRING_ASCII); + autf8 = silc_calloc(payload_len, sizeof(*autf8)); + auth_data_len = silc_utf8_encode(auth_data, auth_data_len, + SILC_STRING_ASCII, autf8, payload_len); + auth_data = autf8; + } + payload_len = 4 + auth_data_len; packet = silc_buffer_alloc(payload_len); silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); @@ -590,6 +602,7 @@ silc_client_conn_auth_continue(unsigned char *auth_data, NULL, 0, NULL, NULL, packet->data, packet->len, TRUE); silc_buffer_free(packet); + silc_free(autf8); /* Next state is end of protocol */ protocol->state = SILC_PROTOCOL_STATE_END; diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index b9647bdf..a1f8e48b 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -345,7 +345,7 @@ typedef struct { /* Called to indicate that connection was either successfully established or connecting failed. This is also the first time application receives - the SilcClientConnection objecet which it should save somewhere. + the SilcClientConnection object which it should save somewhere. If the `success' is FALSE the application must always call the function silc_client_close_connection. */ void (*connect)(SilcClient client, SilcClientConnection conn, int success); @@ -745,22 +745,15 @@ void silc_client_start_key_exchange(SilcClient client, * SYNOPSIS * * void silc_client_close_connection(SilcClient client, - * SilcSocketConnection sock, * SilcClientConnection conn); * * DESCRIPTION * * Closes connection to remote end. Free's all allocated data except * for some information such as nickname etc. that are valid at all time. - * If the `sock' is NULL then the conn->sock will be used. If `sock' is - * provided it will be checked whether the sock and `conn->sock' are the - * same (they can be different, ie. a socket can use `conn' as its - * connection but `conn->sock' might be actually a different connection - * than the `sock'). * ***/ void silc_client_close_connection(SilcClient client, - SilcSocketConnection sock, SilcClientConnection conn); diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c index 6e73a9f4..e38eff0b 100644 --- a/lib/silccore/silcauth.c +++ b/lib/silccore/silcauth.c @@ -92,13 +92,28 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, { SilcBuffer buffer; SilcUInt32 len; + unsigned char *autf8 = NULL; + SilcUInt32 autf8_len; SILC_LOG_DEBUG(("Encoding Authentication Payload")); + /* Passphrase MUST be UTF-8 encoded, encode if it is not */ + if (method == SILC_AUTH_PASSWORD && !silc_utf8_valid(auth_data, auth_len)) { + autf8_len = silc_utf8_encoded_len(auth_data, auth_len, 0); + if (!autf8_len) + return NULL; + autf8 = silc_calloc(autf8_len, sizeof(*autf8)); + auth_len = silc_utf8_encode(auth_data, auth_len, 0, autf8, autf8_len); + auth_data = (const unsigned char *)autf8; + } + len = 2 + 2 + 2 + random_len + 2 + auth_len; buffer = silc_buffer_alloc_size(len); - if (!buffer) + if (!buffer) { + silc_free(autf8); return NULL; + } + silc_buffer_format(buffer, SILC_STR_UI_SHORT(len), SILC_STR_UI_SHORT(method), @@ -108,6 +123,7 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, SILC_STR_UI_XNSTRING(auth_data, auth_len), SILC_STR_END); + silc_free(autf8); return buffer; } @@ -135,7 +151,7 @@ SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload) return payload->auth_method; } -/* Get the authentication data */ +/* Get the authentication data. If this is passphrase it is UTF-8 encoded. */ unsigned char *silc_auth_get_data(SilcAuthPayload payload, SilcUInt32 *auth_len) @@ -392,7 +408,8 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, /* Same as above but parses the authentication payload before verify. */ -bool silc_auth_verify_data(const unsigned char *payload, SilcUInt32 payload_len, +bool silc_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, SilcAuthMethod auth_method, const void *auth_data, SilcUInt32 auth_data_len, SilcHash hash, const void *id, SilcIdType type) diff --git a/lib/silccore/silcauth.h b/lib/silccore/silcauth.h index 38a0a418..f6662132 100644 --- a/lib/silccore/silcauth.h +++ b/lib/silccore/silcauth.h @@ -129,7 +129,10 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, * * Encodes authentication payload into buffer and returns it. * The `random_data' is provided only if doing public key authentication. - * The `auth_data' is the actual authentication data. + * The `auth_data' is the actual authentication data. If the + * `method' is SILC_AUTH_PASSWORD the passphase in `auth_data' sent as + * argument SHOULD be UTF-8 encoded, if not library will attempt to + * encode it. * ***/ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, @@ -173,7 +176,9 @@ SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload); * * DESCRIPTION * - * Get the authentication data. The caller must not free the data. + * Get the authentication data. The caller must not free the data. If + * the authentication method is passphrase, then the returned string + * is UTF-8 encoded passphrase. * ***/ unsigned char *silc_auth_get_data(SilcAuthPayload payload, @@ -266,9 +271,9 @@ bool silc_auth_public_key_auth_verify_data(const unsigned char *payload, * Verifies the authentication data directly from the Authentication * Payload. Supports all authentication methods. If the authentication * method is passphrase based then the `auth_data' and `auth_data_len' - * are the passphrase and its length. If the method is public key - * authentication then the `auth_data' is the SilcPublicKey and the - * `auth_data_len' is ignored. + * are the passphrase and its length. The passphrase MUST be UTF-8 + * encoded. If the method is public key authentication then the + * `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored. * ***/ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, @@ -292,12 +297,13 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, * Verifies the authentication data directly from the Authentication * Payload. Supports all authentication methods. If the authentication * method is passphrase based then the `auth_data' and `auth_data_len' - * are the passphrase and its length. If the method is public key - * authentication then the `auth_data' is the SilcPublicKey and the - * `auth_data_len' is ignored. + * are the passphrase and its length. The passphrase MUST be UTF-8 + * encoded. If the method is public key authentication then the + * `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored. * ***/ -bool silc_auth_verify_data(const unsigned char *payload, SilcUInt32 payload_len, +bool silc_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, SilcAuthMethod auth_method, const void *auth_data, SilcUInt32 auth_data_len, SilcHash hash, const void *id, SilcIdType type); diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 4e7cdcfe..db3a8e25 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -945,7 +945,7 @@ static int silc_pkcs_save_public_key_internal(char *filename, case SILC_PKCS_FILE_BIN: break; case SILC_PKCS_FILE_PEM: - data = silc_encode_pem_file(data, data_len); + data = silc_pem_encode_file(data, data_len); data_len = strlen(data); break; } @@ -1008,7 +1008,7 @@ static int silc_pkcs_save_private_key_internal(char *filename, case SILC_PKCS_FILE_BIN: break; case SILC_PKCS_FILE_PEM: - data = silc_encode_pem_file(data, data_len); + data = silc_pem_encode_file(data, data_len); data_len = strlen(data); break; } @@ -1097,7 +1097,7 @@ int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key, case SILC_PKCS_FILE_BIN: break; case SILC_PKCS_FILE_PEM: - data = silc_decode_pem(data, len, &len); + data = silc_pem_decode(data, len, &len); memset(old, 0, data_len); silc_free(old); old = data; @@ -1154,7 +1154,7 @@ int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key, case SILC_PKCS_FILE_BIN: break; case SILC_PKCS_FILE_PEM: - data = silc_decode_pem(data, len, &len); + data = silc_pem_decode(data, len, &len); break; } diff --git a/lib/silcutil/DIRECTORY b/lib/silcutil/DIRECTORY index 66e1d3a6..37b0a95e 100644 --- a/lib/silcutil/DIRECTORY +++ b/lib/silcutil/DIRECTORY @@ -15,6 +15,7 @@ @LINK=silcprotocol.html:SILC Protocol Interface @LINK=silcconfig.html:SILC Config Interface @LINK=silcfileutil.html:SILC File Util Interface +@LINK=silcstrutil.html:SILC String Util Interface @LINK=silcutil.html:SILC Util Interface @LINK=silclist.html:SILC List Interface @LINK=silcdlist.html:SILC Dynamic List Interface diff --git a/lib/silcutil/Makefile.am b/lib/silcutil/Makefile.am index 5b7f020e..2b65ce0f 100644 --- a/lib/silcutil/Makefile.am +++ b/lib/silcutil/Makefile.am @@ -45,6 +45,7 @@ libsilcutil_a_SOURCES = \ silcnet.c \ silcschedule.c \ silcfileutil.c \ + silcstrutil.c \ silcutil.c \ silchashtable.c \ silcsockconn.c \ @@ -68,6 +69,7 @@ include_HEADERS = \ silcdlist.h \ silcfileutil.h \ silcutil.h \ + silcstrutil.h \ silctypes.h endif diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index fa598945..d1f04883 100644 --- a/lib/silcutil/silcstrutil.c +++ b/lib/silcutil/silcstrutil.c @@ -16,6 +16,7 @@ GNU General Public License for more details. */ +/* $Id$ */ #include "silcincludes.h" #include "silcstrutil.h" diff --git a/lib/silcutil/silcstrutil.h b/lib/silcutil/silcstrutil.h new file mode 100644 index 00000000..746d0ad9 --- /dev/null +++ b/lib/silcutil/silcstrutil.h @@ -0,0 +1,176 @@ +/* + + silcstrutil.h + + Author: Pekka Riikonen + + Copyright (C) 2002 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +/****h* silcutil/SILC String Utilities + * + * DESCRIPTION + * + * String manipulation utility routines. These routines provides + * various helper functions for encoding, decoding and otherwise + * managing strings. + * + ***/ + +#ifndef SILCSTRUTIL_H +#define SILCSTRUTIL_H + +/****f* silcutil/SilcStrUtilAPI/silc_pem_encode + * + * SYNOPSIS + * + * char *silc_pem_encode(unsigned char *data, SilcUInt32 len); + * + * DESCRIPTION + * + * Encodes data into PEM encoding. Returns NULL terminated PEM encoded + * data string. Note: This is originally public domain code and is + * still PD. + * + ***/ +char *silc_pem_encode(unsigned char *data, SilcUInt32 len); + +/****f* silcutil/SilcStrUtilAPI/silc_pem_encode_file + * + * SYNOPSIS + * + * char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len); + * + * DESCRIPTION + * + * Same as silc_pem_encode() but puts newline ('\n') every 72 characters. + * + ***/ +char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len); + +/****f* silcutil/SilcStrUtilAPI/silc_pem_decode + * + * SYNOPSIS + * + * unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len, + * SilcUInt32 *ret_len); + * + * DESCRIPTION + * + * Decodes PEM into data. Returns the decoded data. Note: This is + * originally public domain code and is still PD. + * + ***/ +unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len, + SilcUInt32 *ret_len); + +/****d* silcutil/SilcStrUtilAPI/SilcStringEncoding + * + * NAME + * + * typedef enum { ... } SilcStringEncoding; + * + * DESCRIPTION + * + * String encoding definitions used with the UTF-8 encoding and the + * decoding functions. + * + * SOURCE + */ +typedef enum { + SILC_STRING_ASCII = 0, /* Any 8 bit ASCII encoding (default) */ + + /* Rest are not implemented yet */ + SILC_STRING_ASCII_ESC = 1, /* 7 bit ASCII (>0x7f escaped) */ + SILC_STRING_BMP = 2, /* 16 bit, UCS-2, BMP, ISO/IEC 10646 */ + SILC_STRING_UNIVERSAL = 3, /* 32 bit, UCS-4, Universal, ISO/IEC 10646 */ +} SilcStringEncoding; +/***/ + +/****f* silcutil/SilcStrUtilAPI/silc_utf8_encode + * + * SYNOPSIS + * + * SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len, + * SilcStringEncoding bin_encoding, + * unsigned char *utf8, SilcUInt32 utf8_size); + * + * DESCRIPTION + * + * Encodes the string `bin' of which encoding is `bin_encoding' to the + * UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'. + * Returns the length of the UTF-8 encoded string, or zero (0) on error. + * By default `bin_encoding' is ASCII, and the caller needs to know the + * encoding of the input string if it is anything else. + * + ***/ +SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len, + SilcStringEncoding bin_encoding, + unsigned char *utf8, SilcUInt32 utf8_size); + +/****f* silcutil/SilcStrUtilAPI/silc_utf8_decode + * + * SYNOPSIS + * + * SilcUInt32 silc_utf8_decode(const unsigned char *utf8, + * SilcUInt32 utf8_len, + * SilcStringEncoding bin_encoding, + * unsigned char *bin, SilcUInt32 bin_size); + * + * DESCRIPTION + * + * Decodes UTF-8 encoded string `utf8' to string of which encoding is + * to be `bin_encoding', into the `bin' buffer of size of `bin_size'. + * Returns the length of the decoded buffer, or zero (0) on error. + * By default `bin_encoding' is ASCII, and the caller needs to know to + * which encoding the output string is to be encoded if ASCII is not + * desired. + * + ***/ +SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len, + SilcStringEncoding bin_encoding, + unsigned char *bin, SilcUInt32 bin_size); + +/****f* silcutil/SilcStrUtilAPI/silc_utf8_encoded_len + * + * SYNOPSIS + * + * SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, + * SilcUInt32 bin_len, + * SilcStringEncoding bin_encoding); + * + * DESCRIPTION + * + * Returns the length of UTF-8 encoded string if the `bin' of + * encoding of `bin_encoding' is encoded with silc_utf8_encode. + * + ***/ +SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len, + SilcStringEncoding bin_encoding); + +/****f* silcutil/SilcStrUtilAPI/silc_utf8_valid + * + * SYNOPSIS + * + * bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len); + * + * DESCRIPTION + * + * Returns TRUE if the `utf8' string of length of `utf8_len' is valid + * UTF-8 encoded string, FALSE if it is not UTF-8 encoded string. + * + ***/ +bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len); + + +#endif /* SILCSTRUTIL_H */ diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index f0c0e7b6..e322c2af 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -105,157 +105,6 @@ char *silc_to_upper(char *string) return ret; } -static unsigned char pem_enc[64] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* Encodes data into PEM encoding. Returns NULL terminated PEM encoded - data string. Note: This is originally public domain code and is - still PD. */ - -char *silc_encode_pem(unsigned char *data, SilcUInt32 len) -{ - int i, j; - SilcUInt32 bits, c, char_count; - char *pem; - - char_count = 0; - bits = 0; - j = 0; - - pem = silc_calloc(((len * 8 + 5) / 6) + 5, sizeof(*pem)); - - for (i = 0; i < len; i++) { - c = data[i]; - bits += c; - char_count++; - - if (char_count == 3) { - pem[j++] = pem_enc[bits >> 18]; - pem[j++] = pem_enc[(bits >> 12) & 0x3f]; - pem[j++] = pem_enc[(bits >> 6) & 0x3f]; - pem[j++] = pem_enc[bits & 0x3f]; - bits = 0; - char_count = 0; - } else { - bits <<= 8; - } - } - - if (char_count != 0) { - bits <<= 16 - (8 * char_count); - pem[j++] = pem_enc[bits >> 18]; - pem[j++] = pem_enc[(bits >> 12) & 0x3f]; - - if (char_count == 1) { - pem[j++] = '='; - pem[j] = '='; - } else { - pem[j++] = pem_enc[(bits >> 6) & 0x3f]; - pem[j] = '='; - } - } - - return pem; -} - -/* Same as above but puts newline ('\n') every 72 characters. */ - -char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len) -{ - int i, j; - SilcUInt32 len, cols; - char *pem, *pem2; - - pem = silc_encode_pem(data, data_len); - len = strlen(pem); - - pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2)); - - for (i = 0, j = 0, cols = 1; i < len; i++, cols++) { - if (cols == 72) { - pem2[i] = '\n'; - cols = 0; - len++; - continue; - } - - pem2[i] = pem[j++]; - } - - silc_free(pem); - return pem2; -} - -/* Decodes PEM into data. Returns the decoded data. Note: This is - originally public domain code and is still PD. */ - -unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len, - SilcUInt32 *ret_len) -{ - int i, j; - SilcUInt32 len, c, char_count, bits; - unsigned char *data; - static char ialpha[256], decoder[256]; - - for (i = 64 - 1; i >= 0; i--) { - ialpha[pem_enc[i]] = 1; - decoder[pem_enc[i]] = i; - } - - char_count = 0; - bits = 0; - j = 0; - - if (!pem_len) - len = strlen(pem); - else - len = pem_len; - - data = silc_calloc(((len * 6) / 8), sizeof(*data)); - - for (i = 0; i < len; i++) { - c = pem[i]; - - if (c == '=') - break; - - if (c > 127 || !ialpha[c]) - continue; - - bits += decoder[c]; - char_count++; - - if (char_count == 4) { - data[j++] = bits >> 16; - data[j++] = (bits >> 8) & 0xff; - data[j++] = bits & 0xff; - bits = 0; - char_count = 0; - } else { - bits <<= 6; - } - } - - switch(char_count) { - case 1: - silc_free(data); - return NULL; - break; - case 2: - data[j++] = bits >> 10; - break; - case 3: - data[j++] = bits >> 16; - data[j++] = (bits >> 8) & 0xff; - break; - } - - if (ret_len) - *ret_len = j; - - return data; -} - /* Parse userfqdn string which is in user@fqdn format. */ bool silc_parse_userfqdn(const char *string, char **left, char **right) diff --git a/lib/silcutil/silcutil.h b/lib/silcutil/silcutil.h index 156d8666..1618b4ff 100644 --- a/lib/silcutil/silcutil.h +++ b/lib/silcutil/silcutil.h @@ -21,7 +21,7 @@ * * DESCRIPTION * - * XXX + * Utility functions. * ***/ @@ -85,50 +85,6 @@ char *silc_get_time(); ***/ char *silc_to_upper(char *string); -/****f* silcutil/SilcUtilAPI/silc_encode_pem - * - * SYNOPSIS - * - * char *silc_encode_pem(unsigned char *data, SilcUInt32 len); - * - * DESCRIPTION - * - * Encodes data into PEM encoding. Returns NULL terminated PEM encoded - * data string. Note: This is originally public domain code and is - * still PD. - * - ***/ -char *silc_encode_pem(unsigned char *data, SilcUInt32 len); - -/****f* silcutil/SilcUtilAPI/silc_encode_pem_file - * - * SYNOPSIS - * - * char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len); - * - * DESCRIPTION - * - * Same as silc_encode_pem() but puts newline ('\n') every 72 characters. - * - ***/ -char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len); - -/****f* silcutil/SilcUtilAPI/silc_decode_pem - * - * SYNOPSIS - * - * unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len, - * SilcUInt32 *ret_len); - * - * DESCRIPTION - * - * Decodes PEM into data. Returns the decoded data. Note: This is - * originally public domain code and is still PD. - * - ***/ -unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len, - SilcUInt32 *ret_len); - /****f* silcutil/SilcUtilAPI/silc_parse_userfqdn * * SYNOPSIS -- 2.24.0