From: Pekka Riikonen Date: Wed, 24 Sep 2008 15:18:30 +0000 (+0300) Subject: Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch X-Git-Tag: silc.server.1.1.13 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=e9374395ec9747bddd3ea0bfd3e5a17717e97b31;hp=90e14dc985628e0b0f86e604d511039d302dc956 Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch Signed-off-by: Pekka Riikonen --- diff --git a/apps/silcd/command.c b/apps/silcd/command.c index d8d105c5..2bd8198e 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -1564,12 +1564,13 @@ SILC_SERVER_CMD_FUNC(info) char info_string[256]; memset(info_string, 0, sizeof(info_string)); - snprintf(info_string, sizeof(info_string), - "location: %s server: %s admin: %s <%s>", - server->config->server_info->location, - server->config->server_info->server_type, - server->config->server_info->admin, - server->config->server_info->email); + silc_snprintf(info_string, sizeof(info_string), + "location: %s server: %s admin: %s <%s> version: %s", + server->config->server_info->location, + server->config->server_info->server_type, + server->config->server_info->admin, + server->config->server_info->email, + silc_dist_version); server_info = info_string; entry = server->id_entry; @@ -2830,7 +2831,7 @@ SILC_SERVER_CMD_FUNC(umode) SilcServer server = cmd->server; SilcClientEntry client = silc_packet_get_context(cmd->sock); unsigned char *tmp_mask, m[4]; - SilcUInt32 mask = 0; + SilcUInt32 mask = 0, tmp_len; SilcUInt16 ident = silc_command_get_ident(cmd->payload); SilcBool set_mask = FALSE; @@ -2840,8 +2841,8 @@ SILC_SERVER_CMD_FUNC(umode) SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2); /* Get the client's mode mask */ - tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL); - if (tmp_mask) { + tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); + if (tmp_mask && tmp_len == 4) { SILC_GET32_MSB(mask, tmp_mask); set_mask = TRUE; } @@ -2954,7 +2955,7 @@ SILC_SERVER_CMD_FUNC(cmode) /* Get the channel mode mask */ tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); - if (tmp_mask) { + if (tmp_mask && tmp_len == 4) { SILC_GET32_MSB(mode_mask, tmp_mask); set_mask = TRUE; } diff --git a/apps/silcd/server.c b/apps/silcd/server.c index aff2df5c..c2df082c 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -201,6 +201,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine, if (server->router_conn && server->router_conn->sock == stream && !server->router && server->standalone) { + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_create_connections(server); silc_server_free_sock_user_data(server, stream, NULL); } else { @@ -212,6 +214,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine, server->backup_closed = TRUE; } + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_free_sock_user_data(server, stream, NULL); } @@ -239,6 +243,8 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout) server->backup_closed = TRUE; } + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_free_sock_user_data(server, stream, NULL); } @@ -1322,7 +1328,8 @@ void silc_server_create_connection(SilcServer server, sconn->no_conf = dynamic; sconn->server = server; - SILC_LOG_DEBUG(("Created connection %p", sconn)); + SILC_LOG_DEBUG(("Created connection %p to %s:%d", sconn, + remote_host, port)); silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router, sconn, 0, 0); @@ -1353,7 +1360,15 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, if (success == FALSE) { /* Authentication failed */ - /* XXX retry connecting */ + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); @@ -1448,6 +1463,15 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_ID_SERVER), NULL, sconn->sock); if (!id_entry) { + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_free_sock_user_data(server, sconn->sock, NULL); @@ -1462,6 +1486,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, idata->status |= (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_LOCAL); idata->sconn = sconn; + idata->sconn->callback = NULL; /* Statistics */ server->stat.my_routers++; @@ -1506,8 +1531,9 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_backup_add(server, server->id_entry, ip, sconn->remote_port, TRUE); } + } #if 0 - } else { + else { /* We already have primary router. Disconnect this connection */ SILC_LOG_DEBUG(("We already have primary router, disconnect")); silc_idlist_del_server(server->global_list, id_entry); @@ -1517,8 +1543,8 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_disconnect_remote(server, sconn->sock, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; -#endif /* 0 */ } +#endif /* 0 */ } else { /* Add this server to be our backup router */ id_entry->server_type = SILC_BACKUP_ROUTER; @@ -1573,9 +1599,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, { SilcPacketStream sock = context; SilcUnknownEntry entry = silc_packet_get_context(sock); - SilcServerConnection sconn = entry->data.sconn; - SilcServer server = entry->server; - SilcServerConfigRouter *conn = sconn->conn.ref_ptr; + SilcServerConnection sconn; + SilcServer server; + SilcServerConfigRouter *conn; SilcAuthMethod auth_meth = SILC_AUTH_NONE; void *auth_data = NULL; SilcUInt32 auth_data_len = 0; @@ -1584,17 +1610,28 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SilcHmac hmac_send, hmac_receive; SilcHash hash; - SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry)); - + server = entry->server; + sconn = entry->data.sconn; + conn = sconn->conn.ref_ptr; entry->op = NULL; + SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry)); + if (status != SILC_SKE_STATUS_OK) { /* SKE failed */ SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)", silc_ske_map_status(status), entry->hostname, entry->ip)); - - /* XXX retry connecting */ silc_ske_free(ske); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_free_sock_user_data(server, sconn->sock, NULL); @@ -1608,11 +1645,18 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, /* Set the keys into use. The data will be encrypted after this. */ if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key, &hmac_send, &hmac_receive, &hash)) { + silc_ske_free(ske); - /* XXX retry connecting */ + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } /* Error setting keys */ - silc_ske_free(ske); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_free_sock_user_data(server, sconn->sock, NULL); @@ -1628,10 +1672,18 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, connauth = silc_connauth_alloc(server->schedule, ske, server->config->conn_auth_timeout); if (!connauth) { - /* XXX retry connecting */ + silc_ske_free(ske); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } /** Error allocating auth protocol */ - silc_ske_free(ske); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_free_sock_user_data(server, sconn->sock, NULL); @@ -1688,6 +1740,16 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) if (!sconn->sock) { SILC_LOG_ERROR(("Cannot connect: cannot create packet stream")); silc_stream_destroy(sconn->stream); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); @@ -1698,9 +1760,19 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) /* Set source ID to packet stream */ if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, server->id, 0, NULL)) { + silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_packet_stream_destroy(sconn->sock); silc_server_connection_free(sconn); return; } @@ -1709,6 +1781,18 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) entry = silc_calloc(1, sizeof(*entry)); if (!entry) { silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } @@ -1731,9 +1815,19 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) server->public_key, server->private_key, sconn); if (!ske) { silc_free(entry); + silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_packet_stream_destroy(sconn->sock); silc_server_connection_free(sconn); return; } @@ -1776,7 +1870,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry) /* If we've reached max retry count, give up. */ if ((sconn->retry_count > param->reconnect_count) && - !param->reconnect_keep_trying) { + sconn->no_reconnect) { SILC_LOG_ERROR(("Could not connect, giving up")); if (sconn->callback) @@ -1823,10 +1917,16 @@ static void silc_server_connection_established(SilcNetStatus status, SILC_LOG_ERROR(("Could not connect to %s:%d: %s", sconn->remote_host, sconn->remote_port, silc_net_get_error_string(status))); - - if (sconn->callback) - (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(sconn->server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + } else { + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_connection_free(sconn); + } break; default: @@ -1877,6 +1977,8 @@ SILC_TASK_CALLBACK(silc_server_connect_router) SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect", (sconn->backup ? "backup router" : "router"), sconn->remote_host, sconn->remote_port)); + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } @@ -1893,6 +1995,8 @@ SILC_TASK_CALLBACK(silc_server_connect_router) if (!sconn->op) { SILC_LOG_ERROR(("Could not connect to router %s:%d", sconn->remote_host, sconn->remote_port)); + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } @@ -1911,6 +2015,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) SilcServer server = context; SilcServerConnection sconn; SilcServerConfigRouter *ptr; + SilcServerConfigConnParams *param; /* Don't connect if we are shutting down. */ if (server->server_shutdown) @@ -1986,6 +2091,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) } } + param = (ptr->param ? ptr->param : &server->config->param); + /* Allocate connection object for hold connection specific stuff. */ sconn = silc_calloc(1, sizeof(*sconn)); if (!sconn) @@ -1998,6 +2105,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) sconn->backup_replace_ip = strdup(ptr->backup_replace_ip); sconn->backup_replace_port = ptr->backup_replace_port; } + sconn->no_reconnect = param->reconnect_keep_trying == FALSE; SILC_LOG_DEBUG(("Created connection %p", sconn)); @@ -2498,6 +2606,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, sconn->remote_port = port; silc_dlist_add(server->conns, sconn); idata->sconn = sconn; + idata->sconn->callback = NULL; idata->last_receive = time(NULL); /* Add the common data structure to the ID entry. */ @@ -2712,6 +2821,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, entry->port = port; entry->server = server; entry->data.conn_type = SILC_CONN_UNKNOWN; + entry->data.status |= SILC_IDLIST_STATUS_LOCAL; silc_packet_set_context(packet_stream, entry); SILC_LOG_DEBUG(("Created unknown connection %p", entry)); @@ -3153,7 +3263,7 @@ void silc_server_free_sock_user_data(SilcServer server, /* We'll need to constantly try to reconnect to the primary router so that we'll see when it comes back online. */ - silc_server_create_connection(server, FALSE, FALSE, ip, port, + silc_server_create_connection(server, TRUE, FALSE, ip, port, silc_server_backup_connected, NULL); } diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index e460c95d..8f5140c1 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -786,11 +786,16 @@ SILC_TASK_CALLBACK(silc_server_backup_connected_again) SilcServer server = app_context; SilcServerConfigRouter *primary; + SILC_LOG_DEBUG(("Reconnecting")); + + if (server->server_shutdown) + return; + primary = silc_server_config_get_primary_router(server); if (primary) { if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER, primary->host, primary->port)) - silc_server_create_connection(server, FALSE, FALSE, + silc_server_create_connection(server, TRUE, FALSE, primary->host, primary->port, silc_server_backup_connected, context); @@ -810,6 +815,7 @@ void silc_server_backup_connected(SilcServer server, if (!server_entry) { /* Try again */ + SILC_LOG_DEBUG(("Connecting failed")); silc_schedule_task_add_timeout(server->schedule, silc_server_backup_connected_again, context, 5, 0); @@ -840,7 +846,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_primary_again) if (primary) { if (!silc_server_find_socket_by_host(server, SILC_CONN_ROUTER, primary->host, primary->port)) - silc_server_create_connection(server, FALSE, FALSE, + silc_server_create_connection(server, TRUE, FALSE, primary->host, primary->port, silc_server_backup_connect_primary, context); @@ -1040,7 +1046,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup) SILC_LOG_DEBUG(("Received START (session %d), reconnect to router", ctx->session)); silc_packet_stream_ref(ctx->sock); - silc_server_create_connection(server, FALSE, FALSE, + silc_server_create_connection(server, TRUE, FALSE, primary->host, primary->port, silc_server_backup_connect_primary, ctx->sock); diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index 19ba9193..d367328c 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -745,8 +745,8 @@ int main(int argc, char **argv) silc_file_writefile(pidfile, buf, strlen(buf)); } - silc_server_drop_privs(silcd); } + silc_server_drop_privs(silcd); /* Run the server. When this returns the server has been stopped and we will exit. */ diff --git a/doc/example_silcd.conf.in b/doc/example_silcd.conf.in index 96d43f45..32bb7be4 100644 --- a/doc/example_silcd.conf.in +++ b/doc/example_silcd.conf.in @@ -190,10 +190,12 @@ ServerInfo { # # Primary listener. Specify the IP address and the port to bind - # the server. + # the server. The public_ip can be used to specify the public IP + # if the server is behind NAT. # Primary { ip = "10.2.1.6"; + # public_ip = "11.1.1.1"; port = 706; }; diff --git a/lib/silcasn1/silcasn1.c b/lib/silcasn1/silcasn1.c index 5965228b..2e43b49c 100644 --- a/lib/silcasn1/silcasn1.c +++ b/lib/silcasn1/silcasn1.c @@ -53,7 +53,7 @@ SilcBool silc_asn1_init(SilcAsn1 asn1) asn1->stack2 = silc_stack_alloc(768); if (!asn1->stack2) { - silc_stack_free(asn1->stack2); + silc_stack_free(asn1->stack1); return FALSE; } diff --git a/lib/silcasn1/silcasn1_encode.c b/lib/silcasn1/silcasn1_encode.c index 11b963ec..986909c4 100644 --- a/lib/silcasn1/silcasn1_encode.c +++ b/lib/silcasn1/silcasn1_encode.c @@ -351,7 +351,7 @@ silc_asn1_encoder(SilcAsn1 asn1, SilcStack stack1, SilcStack stack2, /* Get OID words from the string */ cp = strchr(oidstr, '.'); while (cp) { - if (sscanf(oidstr, "%lu", (unsigned long *)&oid) != 1) { + if (sscanf(oidstr, "%u", &oid) != 1) { SILC_LOG_DEBUG(("Malformed OID string")); goto fail; } @@ -362,7 +362,7 @@ silc_asn1_encoder(SilcAsn1 asn1, SilcStack stack1, SilcStack stack2, cp = strchr(oidstr, '.'); if (!cp) { - if (sscanf(oidstr, "%lu", (unsigned long *)&oid) != 1) { + if (sscanf(oidstr, "%u", &oid) != 1) { SILC_LOG_DEBUG(("Malformed OID string")); goto fail; } diff --git a/lib/silcclient/client.h b/lib/silcclient/client.h index ebe41fe9..d66808dc 100644 --- a/lib/silcclient/client.h +++ b/lib/silcclient/client.h @@ -53,16 +53,17 @@ typedef struct SilcClientEntryInternalStruct { SilcUInt32 key_len; /* Key data length */ SilcClientKeyAgreement ke; /* Current key agreement context or NULL */ + SilcAtomic32 refcnt; /* Reference counter */ + SilcAtomic32 deleted; /* Flag indicating whether the client object is + already scheduled for deletion */ + SilcUInt16 resolve_cmd_ident; /* Command identifier when resolving */ + /* Flags */ unsigned int valid : 1; /* FALSE if this entry is not valid. Entry without nickname is not valid. */ unsigned int generated : 1; /* TRUE if library generated `key' */ unsigned int prv_resp : 1; /* TRUE if we are responder when using private message keys. */ - SilcUInt16 resolve_cmd_ident; /* Command identifier when resolving */ - SilcAtomic32 refcnt; /* Reference counter */ - SilcAtomic32 deleted; /* Flag indicating whether the client object is - already scheduled for deletion.*/ } SilcClientEntryInternal; /* Internal channel entry context */ @@ -83,15 +84,16 @@ typedef struct SilcChannelEntryInternalStruct { SilcHmac hmac; /* Current HMAC */ unsigned char iv[SILC_CIPHER_MAX_IV_SIZE]; /* Current IV */ + SilcAtomic32 refcnt; /* Reference counter */ + SilcAtomic32 deleted; /* Flag indicating whether the + channel object is already + scheduled for deletion */ SilcUInt16 resolve_cmd_ident; /* Channel information resolving identifier. This is used when resolving users, and other stuff that relates to the channel. Not used for the channel resolving itself. */ - SilcAtomic32 refcnt; /* Reference counter */ - SilcAtomic32 deleted; /* Flag indicating whether the channel object is - already scheduled for deletion.*/ } SilcChannelEntryInternal; /* Internal server entry context */ diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index 32dac873..4120695d 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -630,7 +630,7 @@ SilcBool silc_client_del_channel_private_keys(SilcClient client, channel->cipher = silc_cipher_get_name(channel->internal.send_key); else channel->cipher = NULL; - if (channel->hmac) + if (channel->internal.hmac) channel->hmac = silc_hmac_get_name(channel->internal.hmac); else channel->hmac = NULL; diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index bdcdd1ca..4664dbaa 100644 --- a/lib/silcclient/client_entry.c +++ b/lib/silcclient/client_entry.c @@ -1010,16 +1010,15 @@ SilcBool silc_client_del_client(SilcClient client, SilcClientConnection conn, if (!client_entry) return FALSE; - if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0) - { - SILC_LOG_DEBUG(("** WARNING ** Deleting a client twice %p", client_entry)); -// asm("int3"); - return FALSE; + SILC_LOG_DEBUG(("Marking client entry %p deleted")); + + if (silc_atomic_sub_int32(&client_entry->internal.deleted, 1) != 0) { + SILC_LOG_DEBUG(("Client entry %p already marked deleted")); + return FALSE; } silc_client_unref_client(client, conn, client_entry); return TRUE; - } /* Internal routine used to find client by ID and if not found this creates @@ -1075,31 +1074,32 @@ SilcClientEntry silc_client_ref_client(SilcClient client, void silc_client_unref_client(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { - if (client_entry) { - SilcBool ret; + SilcBool ret; - SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry, - silc_atomic_get_int32(&client_entry->internal.refcnt), - silc_atomic_get_int32(&client_entry->internal.refcnt) - 1)); + if (!client_entry) + return; - if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0) - return; - - SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry, - silc_atomic_get_int32(&client_entry->internal.deleted))); + SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry, + silc_atomic_get_int32(&client_entry->internal.refcnt), + silc_atomic_get_int32(&client_entry->internal.refcnt) - 1)); - silc_mutex_lock(conn->internal->lock); - ret = silc_idcache_del_by_context(conn->internal->client_cache, - client_entry, NULL); - silc_mutex_unlock(conn->internal->lock); + if (silc_atomic_sub_int32(&client_entry->internal.refcnt, 1) > 0) + return; - if (ret) { - /* Remove from channels */ - silc_client_remove_from_channels(client, conn, client_entry); + SILC_LOG_DEBUG(("Deleting client %p (%d)", client_entry, + silc_atomic_get_int32(&client_entry->internal.deleted))); - /* Free the client entry data */ - silc_client_del_client_entry(client, conn, client_entry); - } + silc_mutex_lock(conn->internal->lock); + ret = silc_idcache_del_by_context(conn->internal->client_cache, + client_entry, NULL); + silc_mutex_unlock(conn->internal->lock); + + if (ret) { + /* Remove from channels */ + silc_client_remove_from_channels(client, conn, client_entry); + + /* Free the client entry data */ + silc_client_del_client_entry(client, conn, client_entry); } } @@ -1709,10 +1709,10 @@ SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, if (!channel) return FALSE; - if (silc_atomic_sub_int32(&channel->internal.deleted, 1) > 0) - { - SILC_LOG_DEBUG(("** WARNING ** Deleting a channel twice %p", channel)); -// asm("int3"); + SILC_LOG_DEBUG(("Marking channel entry %p deleted")); + + if (silc_atomic_sub_int32(&channel->internal.deleted, 1) != 0) { + SILC_LOG_DEBUG(("Channel entry %p already marked deleted")); return FALSE; } @@ -1781,70 +1781,71 @@ SilcChannelEntry silc_client_ref_channel(SilcClient client, void silc_client_unref_channel(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel_entry) { - if (channel_entry) { - SilcIDCacheEntry id_cache; - SilcBool ret = TRUE; - SilcCipher key; - SilcHmac hmac; - char *namec; - - SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry, - silc_atomic_get_int32(&channel_entry->internal.refcnt), - silc_atomic_get_int32(&channel_entry->internal.refcnt) - - 1)); + SilcIDCacheEntry id_cache; + SilcBool ret = TRUE; + SilcCipher key; + SilcHmac hmac; + char *namec; - if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0) - return; + if (!channel_entry) + return; - SILC_LOG_DEBUG(("Deleting channel %p", channel_entry)); + SILC_LOG_DEBUG(("Channel %p refcnt %d->%d", channel_entry, + silc_atomic_get_int32(&channel_entry->internal.refcnt), + silc_atomic_get_int32(&channel_entry->internal.refcnt) + - 1)); - silc_mutex_lock(conn->internal->lock); - if (silc_idcache_find_by_context(conn->internal->channel_cache, channel_entry, + if (silc_atomic_sub_int32(&channel_entry->internal.refcnt, 1) > 0) + return; + + SILC_LOG_DEBUG(("Deleting channel %p", channel_entry)); + + silc_mutex_lock(conn->internal->lock); + if (silc_idcache_find_by_context(conn->internal->channel_cache, channel_entry, &id_cache)) { - namec = id_cache->name; - ret = silc_idcache_del_by_context(conn->internal->channel_cache, + namec = id_cache->name; + ret = silc_idcache_del_by_context(conn->internal->channel_cache, channel_entry, NULL); - silc_free(namec); - } - silc_mutex_unlock(conn->internal->lock); + silc_free(namec); + } + silc_mutex_unlock(conn->internal->lock); - if (!ret) - return; + if (!ret) + return; - silc_client_empty_channel(client, conn, channel_entry); - silc_client_del_channel_private_keys(client, conn, channel_entry); - silc_hash_table_free(channel_entry->user_list); - silc_free(channel_entry->channel_name); - silc_free(channel_entry->topic); - if (channel_entry->founder_key) - silc_pkcs_public_key_free(channel_entry->founder_key); - if (channel_entry->internal.send_key) - silc_cipher_free(channel_entry->internal.send_key); - if (channel_entry->internal.receive_key) - silc_cipher_free(channel_entry->internal.receive_key); - if (channel_entry->internal.hmac) - silc_hmac_free(channel_entry->internal.hmac); - if (channel_entry->internal.old_channel_keys) { - silc_dlist_start(channel_entry->internal.old_channel_keys); - while ((key = silc_dlist_get(channel_entry->internal.old_channel_keys))) - silc_cipher_free(key); - silc_dlist_uninit(channel_entry->internal.old_channel_keys); - } - if (channel_entry->internal.old_hmacs) { - silc_dlist_start(channel_entry->internal.old_hmacs); - while ((hmac = silc_dlist_get(channel_entry->internal.old_hmacs))) - silc_hmac_free(hmac); - silc_dlist_uninit(channel_entry->internal.old_hmacs); - } - if (channel_entry->channel_pubkeys) - silc_argument_list_free(channel_entry->channel_pubkeys, + silc_client_empty_channel(client, conn, channel_entry); + silc_client_del_channel_private_keys(client, conn, channel_entry); + silc_hash_table_free(channel_entry->user_list); + silc_free(channel_entry->channel_name); + silc_free(channel_entry->topic); + if (channel_entry->founder_key) + silc_pkcs_public_key_free(channel_entry->founder_key); + if (channel_entry->internal.send_key) + silc_cipher_free(channel_entry->internal.send_key); + if (channel_entry->internal.receive_key) + silc_cipher_free(channel_entry->internal.receive_key); + if (channel_entry->internal.hmac) + silc_hmac_free(channel_entry->internal.hmac); + if (channel_entry->internal.old_channel_keys) { + silc_dlist_start(channel_entry->internal.old_channel_keys); + while ((key = silc_dlist_get(channel_entry->internal.old_channel_keys))) + silc_cipher_free(key); + silc_dlist_uninit(channel_entry->internal.old_channel_keys); + } + if (channel_entry->internal.old_hmacs) { + silc_dlist_start(channel_entry->internal.old_hmacs); + while ((hmac = silc_dlist_get(channel_entry->internal.old_hmacs))) + silc_hmac_free(hmac); + silc_dlist_uninit(channel_entry->internal.old_hmacs); + } + if (channel_entry->channel_pubkeys) + silc_argument_list_free(channel_entry->channel_pubkeys, SILC_ARGUMENT_PUBLIC_KEY); - silc_atomic_uninit32(&channel_entry->internal.deleted); - silc_atomic_uninit32(&channel_entry->internal.refcnt); - silc_rwlock_free(channel_entry->internal.lock); - silc_schedule_task_del_by_context(conn->client->schedule, channel_entry); - silc_free(channel_entry); - } + silc_atomic_uninit32(&channel_entry->internal.deleted); + silc_atomic_uninit32(&channel_entry->internal.refcnt); + silc_rwlock_free(channel_entry->internal.lock); + silc_schedule_task_del_by_context(conn->client->schedule, channel_entry); + silc_free(channel_entry); } /* Free channel entry list */ diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index 85d8b4e6..f552ca6d 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -40,7 +40,7 @@ struct SilcPacketEngineStruct { SilcMutex lock; /* Engine lock */ SilcRng rng; /* RNG for engine */ SilcHashTable contexts; /* Per scheduler contexts */ - SilcPacketCallbacks *callbacks; /* Packet callbacks */ + const SilcPacketCallbacks *callbacks; /* Packet callbacks */ void *callback_context; /* Context for callbacks */ SilcList streams; /* All streams in engine */ SilcList packet_pool; /* Free list for received packets */ @@ -51,7 +51,7 @@ struct SilcPacketEngineStruct { /* Packet processor context */ typedef struct SilcPacketProcessStruct { SilcPacketType *types; /* Packets to process */ - SilcPacketCallbacks *callbacks; /* Callbacks or NULL */ + const SilcPacketCallbacks *callbacks; /* Callbacks or NULL */ void *callback_context; SilcInt32 priority; /* Priority */ } *SilcPacketProcess; @@ -540,7 +540,7 @@ static void silc_packet_engine_context_destr(void *key, void *context, SilcPacketEngine silc_packet_engine_start(SilcRng rng, SilcBool router, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context) { SilcPacketEngine engine; @@ -1001,7 +1001,7 @@ void silc_packet_stream_set_iv_included(SilcPacketStream stream) /* Links `callbacks' to `stream' for specified packet types */ static SilcBool silc_packet_stream_link_va(SilcPacketStream stream, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context, int priority, va_list ap) { @@ -1080,7 +1080,7 @@ static SilcBool silc_packet_stream_link_va(SilcPacketStream stream, /* Links `callbacks' to `stream' for specified packet types */ SilcBool silc_packet_stream_link(SilcPacketStream stream, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context, int priority, ...) { @@ -1098,7 +1098,7 @@ SilcBool silc_packet_stream_link(SilcPacketStream stream, /* Unlinks `callbacks' from `stream'. */ void silc_packet_stream_unlink(SilcPacketStream stream, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context) { SilcPacketProcess p; @@ -1324,6 +1324,7 @@ SilcBool silc_packet_set_ids(SilcPacketStream stream, { SilcUInt32 len; unsigned char tmp[32]; + void *tmp_id; if (!src_id && !dst_id) return FALSE; @@ -1333,17 +1334,17 @@ SilcBool silc_packet_set_ids(SilcPacketStream stream, if (src_id) { SILC_LOG_DEBUG(("Setting source ID to packet stream %p", stream)); - silc_free(stream->src_id); - stream->src_id = NULL; if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) { silc_mutex_unlock(stream->lock); return FALSE; } - stream->src_id = silc_memdup(tmp, len); - if (!stream->src_id) { + tmp_id = silc_memdup(tmp, len); + if (!tmp_id) { silc_mutex_unlock(stream->lock); return FALSE; } + silc_free(stream->src_id); + stream->src_id = tmp_id; stream->src_id_type = src_id_type; stream->src_id_len = len; } @@ -1351,17 +1352,17 @@ SilcBool silc_packet_set_ids(SilcPacketStream stream, if (dst_id) { SILC_LOG_DEBUG(("Setting destination ID to packet stream %p", stream)); - silc_free(stream->dst_id); - stream->dst_id = NULL; if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) { silc_mutex_unlock(stream->lock); return FALSE; } - stream->dst_id = silc_memdup(tmp, len); - if (!stream->dst_id) { + tmp_id = silc_memdup(tmp, len); + if (!tmp_id) { silc_mutex_unlock(stream->lock); return FALSE; } + silc_free(stream->dst_id); + stream->dst_id = tmp_id; stream->dst_id_type = dst_id_type; stream->dst_id_len = len; } @@ -2343,7 +2344,7 @@ silc_packet_wait_packet_receive(SilcPacketEngine engine, void *stream_context); /* Packet waiting callbacks */ -static SilcPacketCallbacks silc_packet_wait_cbs = +static const SilcPacketCallbacks silc_packet_wait_cbs = { silc_packet_wait_packet_receive, NULL, NULL }; @@ -2532,7 +2533,7 @@ typedef struct { } *SilcPacketWrapperStream; /* Packet wrapper callbacks */ -static SilcPacketCallbacks silc_packet_wrap_cbs = +static const SilcPacketCallbacks silc_packet_wrap_cbs = { silc_packet_wrap_packet_receive, NULL, NULL }; diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 3d4ca10d..0caf10d8 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -361,7 +361,7 @@ typedef struct { ***/ SilcPacketEngine silc_packet_engine_start(SilcRng rng, SilcBool router, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context); /****f* silccore/SilcPacketAPI/silc_packet_engine_stop @@ -651,7 +651,7 @@ SilcStream silc_packet_stream_get_stream(SilcPacketStream stream); * ***/ SilcBool silc_packet_stream_link(SilcPacketStream stream, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context, int priority, ...); @@ -671,7 +671,7 @@ SilcBool silc_packet_stream_link(SilcPacketStream stream, * ***/ void silc_packet_stream_unlink(SilcPacketStream stream, - SilcPacketCallbacks *callbacks, + const SilcPacketCallbacks *callbacks, void *callback_context); /****f* silccore/SilcPacketAPI/SilcPacketWrapCoder diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 89e4a848..caf25796 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2007 Pekka Riikonen + Copyright (C) 2000 - 2008 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 @@ -2026,15 +2026,9 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) silc_packet_free(ske->packet); ske->packet = NULL; - /* Verify the received public key and verify the signature if we are - doing mutual authentication. */ - if (ske->start_payload && - ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) { - - SILC_LOG_DEBUG(("We are doing mutual authentication")); - - if (!recv_payload->pk_data && (ske->callbacks->verify_key || - ske->repository)) { + /* Verify public key, except in rekey, when it is not sent */ + if (!ske->rekey) { + if (!recv_payload->pk_data) { /** Public key not provided */ SILC_LOG_ERROR(("Remote end did not send its public key (or " "certificate), even though we require it")); @@ -2044,8 +2038,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) } /* Decode the remote's public key */ - if (recv_payload->pk_data && - !silc_pkcs_public_key_alloc(recv_payload->pk_type, + if (!silc_pkcs_public_key_alloc(recv_payload->pk_type, recv_payload->pk_data, recv_payload->pk_len, &ske->prop->public_key)) { @@ -2056,39 +2049,36 @@ SILC_FSM_STATE(silc_ske_st_responder_phase2) return SILC_FSM_CONTINUE; } - if (ske->prop->public_key && (ske->callbacks->verify_key || - ske->repository)) { - SILC_LOG_DEBUG(("Verifying public key")); + SILC_LOG_DEBUG(("Verifying public key")); - /** Waiting public key verification */ - silc_fsm_next(fsm, silc_ske_st_responder_phase4); + /** Waiting public key verification */ + silc_fsm_next(fsm, silc_ske_st_responder_phase4); - /* If repository is provided, verify the key from there. */ - if (ske->repository) { - SilcSKRFind find; + /* If repository is provided, verify the key from there. */ + if (ske->repository) { + SilcSKRFind find; - find = silc_skr_find_alloc(); - if (!find) { - ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; - silc_fsm_next(fsm, silc_ske_st_responder_error); - return SILC_FSM_CONTINUE; - } - silc_skr_find_set_pkcs_type(find, - silc_pkcs_get_type(ske->prop->public_key)); - silc_skr_find_set_public_key(find, ske->prop->public_key); - silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT); - - /* Find key from repository */ - SILC_FSM_CALL(silc_skr_find(ske->repository, - silc_fsm_get_schedule(fsm), find, - silc_ske_skr_callback, ske)); - } else { - /* Verify from application */ + find = silc_skr_find_alloc(); + if (!find) { + ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY; + silc_fsm_next(fsm, silc_ske_st_responder_error); + return SILC_FSM_CONTINUE; + } + silc_skr_find_set_pkcs_type(find, + silc_pkcs_get_type(ske->prop->public_key)); + silc_skr_find_set_public_key(find, ske->prop->public_key); + silc_skr_find_set_usage(find, SILC_SKR_USAGE_KEY_AGREEMENT); + + /* Find key from repository */ + SILC_FSM_CALL(silc_skr_find(ske->repository, + silc_fsm_get_schedule(fsm), find, + silc_ske_skr_callback, ske)); + } else { + /* Verify from application */ + if (ske->callbacks->verify_key) SILC_FSM_CALL(ske->callbacks->verify_key(ske, ske->prop->public_key, ske->callbacks->context, silc_ske_pk_verified, NULL)); - } - /* NOT REACHED */ } } @@ -2129,7 +2119,7 @@ SILC_FSM_STATE(silc_ske_st_responder_phase4) unsigned char hash[SILC_HASH_MAXLEN]; SilcUInt32 hash_len; - SILC_LOG_DEBUG(("Public key is authentic")); + SILC_LOG_DEBUG(("We are doing mutual authentication")); /* Compute the hash value */ status = silc_ske_make_hash(ske, hash, &hash_len, TRUE); diff --git a/lib/silcutil/silctypes.h b/lib/silcutil/silctypes.h index 70bc3016..d7f97976 100644 --- a/lib/silcutil/silctypes.h +++ b/lib/silcutil/silctypes.h @@ -177,14 +177,14 @@ typedef signed short SilcInt16; * * SOURCE */ -#if SILC_SIZEOF_LONG == 4 -typedef unsigned long SilcUInt32; -typedef signed long SilcInt32; -#else #if SILC_SIZEOF_INT == 4 typedef unsigned int SilcUInt32; typedef signed int SilcInt32; #else +#if SILC_SIZEOF_LONG == 4 +typedef unsigned long SilcUInt32; +typedef signed long SilcInt32; +#else #if SILC_SIZEOF_LONG_LONG >= 4 #ifndef WIN32 typedef unsigned long long SilcUInt32; @@ -634,4 +634,11 @@ do { \ #endif /***/ +typedef char __check_size1[sizeof(SilcInt8) == 1 ? 1 : -1]; +typedef char __check_size2[sizeof(SilcUInt8) == 1 ? 1 : -1]; +typedef char __check_size3[sizeof(SilcInt16) == 2 ? 1 : -1]; +typedef char __check_size4[sizeof(SilcUInt16) == 2 ? 1 : -1]; +typedef char __check_size5[sizeof(SilcInt32) == 4 ? 1 : -1]; +typedef char __check_size6[sizeof(SilcUInt32) == 4 ? 1 : -1]; + #endif /* SILCTYPES_H */