+Sun Feb 3 17:20:52 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed the file transfer's key agreement payload to include
+ zero port also if the hostname is NULL because it could not
+ be bound.
+
+ Call file transfer monitor callback now also if error occurs
+ during key agreement protocol.
+
+ Changed the silc_client_file_send interface to return the
+ SilcClientFileError instead of session id. The session ID
+ is returned into pointer provided as argument.
+
+ Check that the file exists locally before sending the
+ file transfer request at all.
+
+ Affected file lib/silcclient/client_ftp.c, silcapi.h.
+
+ * Added SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED file transfer
+ error than can occur while key agreement protocol. Affected
+ file lib/silcclient/silcapi.h.
+
+ * Fixed the event_mode CMODE handler to not crash when mode
+ is changed and +k mode is set in the channel. Affected file
+ irssi/src/silc/core/silc-channels.c.
+
+ * Fixed SILC_LOG_ERROR to give out Error and not Warning, and
+ SILC_LOG_WARNING to give out Warning and not Error. Affected
+ file lib/silcutil/silclog.c.
+
+ * Fixed the channel message payload decryption in the function
+ silc_channel_message_payload_decrypt to not modify the original
+ buffer before it is verified that the message decrypted
+ correctly. Otherwise, next time it is called with correct
+ channel key it won't encrypt since the payload is corrupted.
+ Affected file lib/silccore/silcchannel.c.
+
Sun Feb 3 11:46:12 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Do not constantly resize the window. A fix patch by cras.
$(INSTALL_DATA) $(srcdir)/INSTALL $(docdir)/
$(INSTALL_DATA) $(srcdir)/TODO $(docdir)/
+toolkit-install:
+ -mkdir -p $(docdir)/toolkit/
+ -$(INSTALL_DATA) $(srcdir)/doc/toolkit/silc* $(docdir)/toolkit
+ -$(INSTALL_DATA) $(srcdir)/doc/toolkit/index* $(docdir)/toolkit
+
examples-install:
-mkdir -p $(docdir)/examples/
$(INSTALL_DATA) $(srcdir)/doc/examples/README $(docdir)/examples/
if SILC_DIST_CLIENT
install-data-hook: install-dirs sim-install doc-install etc-install
else
+if SILC_DIST_TOOLKIT
+install-data-hook: install-dirs generate-server-key sim-install doc-install toolkit-install examples-install etc-install
+else
install-data-hook: install-dirs generate-server-key sim-install doc-install examples-install etc-install
endif
+endif
TODO/bugs In SILC Client Library
================================
- o Rewrite the channel's user list thingy and cross list it to the
- Client entry.
-
o The PRIVATE_MESSAGE_KEY packet is not handled (it is implemented
though). This should be added and perhaps new client operation
should be added to notify application that it was received and
TODO/bugs In SILC Server
========================
+ o Assure that server is allowed to connect only once to router. Meaning
+ if server connection is established already, same connection cannot be
+ established again.
+
o If server send CUMODE_CHANGE notify (like setting founder) to router
and router does not have founder on channel (founder is left or there's
no founder on channel at all), the router will accept the server's
o Make the normal server save user counts with LIST command reply.
+ o Add hashed passwords to silcd.conf file.
+
o The router should check for validity of received notify packets from
servers (after all buggy servers may send notify that is actually
something that should have not been sent).
- o Add hashed passwords to silcd.conf file.
-
- o Backup router related issues
-
- o Channel user mode changes are notified unnecessarely when
- switching to backup router on router crash.
-
o Add a timeout to handling incoming JOIN commands. It should be
enforced that JOIN command is executed only once in a second or two
seconds. Now it is possible to accept n incoming JOIN commands
each JOIN command will create and distribute the new channel key
to everybody on the channel.
+ o Backup router related issues
+
+ o Channel user mode changes are notified unnecessarely when
+ switching to backup router on router crash.
+
o New configuration file format must be added. The following
tasks relates closely to this as well and must be done at the same time
when adding the new config file format:
o Add SilcAsyncOperation to utility library. Any function that takes
callback as an argument must return SilcAsyncOperation.
+ o Add DSS support.
+
o Cipher optimizations (asm, that this) at least for i386 would be nice.
o Add builtin SOCKS and HTTP Proxy support, well the SOCKS at least.
{ "bad_nick", "Bad nickname {hilight $0}", 1, { 0 } },
{ "unknown_notify", "Unknown notify type {hilight $0}", 1, { 0 } },
{ "ke_bad_version", "You are running an incompatible client version (it may be too old or too new) ", 0 },
- { "ke_unsupported_public_key", "Server does not support your public key type", 0 },
- { "ke_unknown_group", "Server does not support one of your proposed KE group", 0 },
- { "ke_unknown_cipher", "Server does not support one of your proposed cipher", 0 },
- { "ke_unknown_pkcs", "Server does not support one of your proposed PKCS", 0 },
- { "ke_unknown_hash_function", "Server does not support one of your proposed hash function", 0 },
- { "ke_unknown_hmac", "Server does not support one of your proposed HMAC", 0 },
+ { "ke_unsupported_public_key", "Remote does not trust/support your public key", 0 },
+ { "ke_unknown_group", "Remote does not support one of your proposed KE group", 0 },
+ { "ke_unknown_cipher", "Remote does not support one of your proposed cipher", 0 },
+ { "ke_unknown_pkcs", "Remote does not support one of your proposed PKCS", 0 },
+ { "ke_unknown_hash_function", "Remote does not support one of your proposed hash function", 0 },
+ { "ke_unknown_hmac", "Remote does not support one of your proposed HMAC", 0 },
{ "ke_incorrect_signature", "Incorrect signature", 0 },
{ "ke_invalid_cookie", "Invalid cookie", 0 },
{ "auth_failed", "Authentication failed", 0 },
#define is_big5_lox(lo) (((char)0x80<=lo)&&(lo<=(char)0xFE)) /* extended */
#define is_big5_hi(hi) (((char)0x81<=hi)&&(hi<=(char)0xFE))
#define is_big5(hi,lo) is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo))
-#endif WANT_BIG5
+#endif
void screen_check_resizes(void);
silc_client_get_clients_by_list(client, conn, list_count, client_id_list,
silc_client_join_get_users,
channel_entry);
+
break;
}
char userhost[256];
SilcIdType idtype;
- idtype = va_arg(va, int);
+ idtype = va_arg(va, SilcIdType);
entry = va_arg(va, void *);
topic = va_arg(va, char *);
channel = va_arg(va, SilcChannelEntry);
channel = va_arg(va, SilcChannelEntry);
mode = silc_client_chmode(modei,
- channel->channel_key->cipher->name,
- silc_hmac_get_name(channel->hmac));
-
+ channel->channel_key ?
+ channel->channel_key->cipher->name : "",
+ channel->hmac ?
+ silc_hmac_get_name(channel->hmac) : "");
+
chanrec = silc_channel_find_entry(server, channel);
if (chanrec != NULL) {
g_free_not_null(chanrec->mode);
FtpSession ftp;
char *local_ip = NULL;
uint32 local_port = 0;
+ uint32 session_id;
if (!server || !IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
if (argc >= 6)
local_port = atoi(argv[5]);
- ftp = silc_calloc(1, sizeof(*ftp));
- ftp->session_id =
+ ret =
silc_client_file_send(silc_client, conn, silc_client_file_monitor,
server, local_ip, local_port,
- client_entry, argv[2]);
+ client_entry, argv[2], &session_id);
+ if (ret == SILC_CLIENT_FILE_OK) {
+ ftp = silc_calloc(1, sizeof(*ftp));
+ ftp->session_id = session_id;
- printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
- SILCTXT_FILE_SEND, client_entry->nickname,
- argv[2]);
-
- ftp->client_entry = client_entry;
- ftp->filepath = strdup(argv[2]);
- ftp->conn = conn;
- ftp->send = TRUE;
- silc_dlist_add(server->ftp_sessions, ftp);
- server->current_session = ftp;
+ printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+ SILCTXT_FILE_SEND, client_entry->nickname,
+ argv[2]);
+
+ ftp->client_entry = client_entry;
+ ftp->filepath = strdup(argv[2]);
+ ftp->conn = conn;
+ ftp->send = TRUE;
+ silc_dlist_add(server->ftp_sessions, ftp);
+ server->current_session = ftp;
+ } else {
+ if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
+ client_entry->nickname);
+ if (ret == SILC_CLIENT_FILE_NO_SUCH_FILE)
+ printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+ SILCTXT_FILE_ERROR_NO_SUCH_FILE,
+ client_entry->nickname, argv[2]);
+ }
break;
return;
}
} else {
- SILC_LOG_DEBUG(("No configuration for remote connection"));
- SILC_LOG_ERROR(("Remote connection not configured"));
+ SILC_LOG_DEBUG(("No configuration for remote client connection"));
+ SILC_LOG_ERROR(("Remote client connection not configured"));
SILC_LOG_ERROR(("Authentication failed"));
silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
return;
}
} else {
- SILC_LOG_DEBUG(("No configuration for remote connection"));
- SILC_LOG_ERROR(("Remote connection not configured"));
+ SILC_LOG_DEBUG(("No configuration for remote server connection"));
+ SILC_LOG_ERROR(("Remote server connection not configured"));
SILC_LOG_ERROR(("Authentication failed"));
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute(protocol, server->schedule,
return;
}
} else {
- SILC_LOG_DEBUG(("No configuration for remote connection"));
- SILC_LOG_ERROR(("Remote connection not configured"));
+ SILC_LOG_DEBUG(("No configuration for remote router connection"));
+ SILC_LOG_ERROR(("Remote router connection not configured"));
SILC_LOG_ERROR(("Authentication failed"));
silc_free(auth_data);
protocol->state = SILC_PROTOCOL_STATE_ERROR;
silcincludes.h \
silcwin32.h \
version.h \
- version_internal.h
+ version_internal.h \
+ silcdefs.h
endif
EXTRA_DIST = \
-rm -rf libsilc.a
-rm -rf libsilcclient.a
+if SILC_DIST_TOOLKIT
+install-exec-hook:
+ -mkdir -p $(libdir)
+ -$(INSTALL) libsilc.a $(libdir)/
+ -$(INSTALL) libsilcclient.a $(libdir)/
+endif
+
if SILC_DIST_WIN32DLL
# WIN32 DLL generation
silc.dll: libsilc.a
we will use the old key in decryption. If that fails too then we
cannot do more and will drop the packet. */
if (!payload) {
- if (!channel->old_channel_key)
+ SILC_LOG_ERROR(("decr failed"));
+ if (!channel->old_channel_key) {
+ SILC_LOG_ERROR(("no old key"));
goto out;
+ }
payload = silc_channel_message_payload_parse(buffer->data, buffer->len,
channel->old_channel_key,
channel->old_hmac);
- if (!payload)
+ if (!payload) {
+ SILC_LOG_ERROR(("old decr failed"));
goto out;
+ }
}
} else if (channel->private_keys) {
SilcChannelPrivateKey entry;
if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
+ /* Call monitor callback */
+ if (session->monitor)
+ (*session->monitor)(session->client, session->conn,
+ SILC_CLIENT_FILE_MONITOR_ERROR,
+ SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED, 0, 0,
+ session->client_entry, session->session_id,
+ session->filepath, session->monitor_context);
+
/* Error occured during protocol */
silc_ske_free_key_material(ctx->keymat);
goto out;
indicated by the `client_entry'. This will negotiate a secret key
with the remote client before actually starting the transmission of
the file. The `monitor' callback will be called to monitor the
- transmission of the file.
-
- This returns a file session ID for the file transmission. It can
- be used to close the session (and abort the file transmission) by
- calling the silc_client_file_close function. The session ID is
- also returned in the `monitor' callback. This returns 0 if the
- file indicated by the `filepath' is being transmitted to the remote
- client indicated by the `client_entry', already. */
-
-uint32 silc_client_file_send(SilcClient client,
- SilcClientConnection conn,
- SilcClientFileMonitor monitor,
- void *monitor_context,
- const char *local_ip,
- uint32 local_port,
- SilcClientEntry client_entry,
- const char *filepath)
+ transmission of the file. */
+
+SilcClientFileError
+silc_client_file_send(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientFileMonitor monitor,
+ void *monitor_context,
+ const char *local_ip,
+ uint32 local_port,
+ SilcClientEntry client_entry,
+ const char *filepath,
+ uint32 *session_id)
{
SilcClientFtpSession session;
SilcBuffer keyagr, ftp;
char *filename, *path;
+ int fd;
SILC_LOG_DEBUG(("Start"));
/* Check for existing session for `filepath'. */
silc_dlist_start(conn->ftp_sessions);
while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
- if (!strcmp(session->filepath, filepath) &&
+ if (session->filepath && !strcmp(session->filepath, filepath) &&
session->client_entry == client_entry)
- return 0;
+ return SILC_CLIENT_FILE_ALREADY_STARTED;
}
+ /* See whether the file exists, and can be opened in generally speaking */
+ fd = silc_file_open(filepath, O_RDONLY);
+ if (fd < 0)
+ return SILC_CLIENT_FILE_NO_SUCH_FILE;
+ silc_file_close(fd);
+
/* Add new session */
session = silc_calloc(1, sizeof(*session));
session->session_id = ++conn->next_session_id;
SILC_LOG_DEBUG(("Could not create listener"));
silc_free(session->hostname);
session->hostname = NULL;
+ session->port = 0;
} else {
/* Listener ready */
session->port = silc_net_get_local_port(session->listener);
silc_buffer_free(ftp);
silc_free(path);
- return session->session_id;
+ if (session_id)
+ *session_id = session->session_id;
+
+ return SILC_CLIENT_FILE_OK;
}
/* Receives a file from a client indicated by the `client_entry'. The
hostname = silc_key_agreement_get_hostname(payload);
port = silc_key_agreement_get_port(payload);
+ if (!hostname)
+ port = 0;
+ if (!port)
+ hostname = NULL;
if (session == SILC_LIST_END || (!hostname && !port)) {
/* No session found, create one and let the application know about
SILC_CLIENT_FILE_ALREADY_STARTED,
SILC_CLIENT_FILE_NO_SUCH_FILE,
SILC_CLIENT_FILE_PERMISSION_DENIED,
+ SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED,
} SilcClientFileError;
/***/
*
* SYNOPSIS
*
- * uint32 silc_client_file_send(SilcClient client,
- * SilcClientConnection conn,
- * SilcClientFileMonitor monitor,
- * void *monitor_context,
- * const char *local_ip,
- * uint32 local_port,
- * SilcClientEntry client_entry,
- * const char *filepath);
+ * SilcClientFileError
+ * silc_client_file_send(SilcClient client,
+ * SilcClientConnection conn,
+ * SilcClientFileMonitor monitor,
+ * void *monitor_context,
+ * const char *local_ip,
+ * uint32 local_port,
+ * SilcClientEntry client_entry,
+ * const char *filepath);
+ * uint32 *session_id);
*
* DESCRIPTION
*
* the file. The `monitor' callback will be called to monitor the
* transmission of the file.
*
- * This returns a file session ID for the file transmission. It can
- * be used to close the session (and abort the file transmission) by
- * calling the silc_client_file_close function. The session ID is
- * also returned in the `monitor' callback. This returns 0 if the
- * file indicated by the `filepath' is being transmitted to the remote
- * client indicated by the `client_entry', already.
+ * This returns a file session ID for the file transmission to the
+ * `session_id' pointer.. It can be used to close the session (and
+ * abort the file transmission) by calling the silc_client_file_close
+ * function. The session ID is also returned in the `monitor' callback.
*
* If the `local_ip' is provided then this will try to bind the
* listener for key exchange protocol to that IP. If `local_port' is
* session.
*
***/
-uint32 silc_client_file_send(SilcClient client,
- SilcClientConnection conn,
- SilcClientFileMonitor monitor,
- void *monitor_context,
- const char *local_ip,
- uint32 local_port,
- SilcClientEntry client_entry,
- const char *filepath);
+SilcClientFileError
+silc_client_file_send(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientFileMonitor monitor,
+ void *monitor_context,
+ const char *local_ip,
+ uint32 local_port,
+ SilcClientEntry client_entry,
+ const char *filepath,
+ uint32 *session_id);
/****f* silcclient/SilcClientAPI/silc_client_file_receive
*
unsigned char *iv;
};
-/* Decrypts the channel message payload. */
-
-int silc_channel_message_payload_decrypt(unsigned char *data,
- size_t data_len,
- SilcCipher cipher,
- SilcHmac hmac)
+/* Decrypts the channel message payload. First push the IV out of the
+ packet. The IV is used in the decryption process. Then decrypt the
+ message. After decyprtion, take the MAC from the decrypted packet,
+ compute MAC and compare the MACs. If they match, the decryption was
+ successful and we have the channel message ready to be displayed. */
+
+bool silc_channel_message_payload_decrypt(unsigned char *data,
+ size_t data_len,
+ SilcCipher cipher,
+ SilcHmac hmac)
{
uint32 iv_len, mac_len;
unsigned char *end, *mac, mac2[32];
+ unsigned char *dst, iv[SILC_CIPHER_MAX_IV_SIZE];
- /* Decrypt the channel message. First push the IV out of the packet.
- The IV is used in the decryption process. Then decrypt the message.
- After decyprtion, take the MAC from the decrypted packet, compute MAC
- and compare the MACs. If they match, the decryption was successfull
- and we have the channel message ready to be displayed. */
+ /* Push the IV out of the packet, and copy the IV since we do not want
+ to modify the original data buffer. */
end = data + data_len;
-
- /* Push the IV out of the packet */
iv_len = silc_cipher_get_block_len(cipher);
+ memcpy(iv, end - iv_len, iv_len);
+
+ /* Allocate destination decryption buffer since we do not want to modify
+ the original data buffer, since we might want to call this function
+ many times for same payload. */
+ if (hmac)
+ dst = silc_calloc(data_len - iv_len, sizeof(*dst));
+ else
+ dst = data;
/* Decrypt the channel message */
- silc_cipher_decrypt(cipher, data, data, data_len - iv_len, (end - iv_len));
+ silc_cipher_decrypt(cipher, data, dst, data_len - iv_len, iv);
- /* Take the MAC */
if (hmac) {
+ /* Take the MAC */
+ end = dst + (data_len - iv_len);
mac_len = silc_hmac_len(hmac);
- mac = (end - iv_len - mac_len);
+ mac = (end - mac_len);
/* Check the MAC of the message */
SILC_LOG_DEBUG(("Checking channel message MACs"));
- silc_hmac_make(hmac, data, (data_len - iv_len - mac_len), mac2, &mac_len);
+ silc_hmac_make(hmac, dst, (data_len - iv_len - mac_len), mac2, &mac_len);
if (memcmp(mac, mac2, mac_len)) {
SILC_LOG_DEBUG(("Channel message MACs does not match"));
+ silc_free(dst);
return FALSE;
}
SILC_LOG_DEBUG(("MAC is Ok"));
+
+ /* Now copy the decrypted data into the buffer since it is verified
+ it decrypted correctly. */
+ memcpy(data, dst, data_len - iv_len);
+ memset(dst, 0, data_len - iv_len);
+ silc_free(dst);
}
return TRUE;
*
* SYNOPSIS
*
- * int silc_channel_message_payload_decrypt(unsigned char *data,
- * size_t data_len,
- * SilcCipher cipher,
- * SilcHmac hmac);
+ * bool silc_channel_message_payload_decrypt(unsigned char *data,
+ * size_t data_len,
+ * SilcCipher cipher,
+ * SilcHmac hmac);
*
* DESCRIPTION
*
* not verified.
*
***/
-int silc_channel_message_payload_decrypt(unsigned char *data,
- size_t data_len,
- SilcCipher cipher,
- SilcHmac hmac);
+bool silc_channel_message_payload_decrypt(unsigned char *data,
+ size_t data_len,
+ SilcCipher cipher,
+ SilcHmac hmac);
/****f* silccore/SilcChannelAPI/silc_channel_message_payload_parse
*
/* These are the known logging channels */
static struct SilcLogStruct silclogs[SILC_LOG_MAX] = {
{NULL, NULL, 0, "Info", SILC_LOG_INFO, NULL, NULL},
- {NULL, NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL},
{NULL, NULL, 0, "Warning", SILC_LOG_WARNING, NULL, NULL},
+ {NULL, NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL},
{NULL, NULL, 0, "Fatal", SILC_LOG_FATAL, NULL, NULL},
};
{
if (!silc_debug)
goto end;
+
if (silc_log_debug_string &&
- !silc_string_regex_match(silc_log_debug_string, file) &&
- !silc_string_regex_match(silc_log_debug_string, function))
+ !silc_string_regex_match(silc_log_debug_string, file) &&
+ !silc_string_regex_match(silc_log_debug_string, function))
goto end;
+
if (silc_log_debug_cb) {
if ((*silc_log_debug_cb)(file, function, line, string,
silc_log_debug_context))
goto end;
}
+
fprintf(stderr, "%s:%d: %s\n", function, line, string);
fflush(stderr);
-end:
+
+ end:
silc_free(string);
}
if (!silc_debug_hexdump)
goto end;
+
if (silc_log_debug_string &&
- !silc_string_regex_match(silc_log_debug_string, file) &&
- !silc_string_regex_match(silc_log_debug_string, function))
+ !silc_string_regex_match(silc_log_debug_string, file) &&
+ !silc_string_regex_match(silc_log_debug_string, function))
goto end;
+
if (silc_log_hexdump_cb) {
if ((*silc_log_hexdump_cb)(file, function, line, data_in, len, string,
silc_log_hexdump_context))
}
fprintf(stderr, "%s:%d: %s\n", function, line, string);
- silc_free(string);
k = 0;
pos = 0;
if (count < 16)
break;
}
- return;
-end:
+ end:
silc_free(string);
}