Select Git revision
aes-set-encrypt-key.c
prot-a.c 12.47 KiB
/*
* $Id: prot-a.c,v 0.82 2003/08/05 09:50:57 ceder Exp $
* Copyright (C) 1991-2002 Lysator Academic Computer Association.
*
* This file is part of the LysKOM server.
*
* LysKOM 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; either version 1, or (at your option)
* any later version.
*
* LysKOM 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.
*
* You should have received a copy of the GNU General Public License
* along with LysKOM; see the file COPYING. If not, write to
* Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
* or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* Please mail bug reports to bug-lyskom@lysator.liu.se.
*/
/*
* Protocol A.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#endif
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#endif
#include <setjmp.h>
#include "timewrap.h"
#include <sys/types.h>
#include <sys/socket.h>
#include "oop.h"
#include "misc-types.h"
#include "s-string.h"
#include "kom-types.h"
#include "com.h"
#include "async.h"
#include "connections.h"
#include "debug.h"
#include "isc-interface.h"
#include "kom-errno.h"
#include "server/smalloc.h"
#include "prot-a.h"
#include "prot-a-output.h"
#include "prot-a-parse.h"
#include "isc-parse.h"
#include "param.h"
#include "kom-memory.h"
BUGDECL;
void
prot_a_reply(Connection *client,
Success status,
union result_holder *res)
{
/*
* The function is called. Now return the answer.
*/
if ( status == OK )
{
isc_putc('=', client->isc_session);
isc_putul(client->ref_no, client->isc_session);
switch ( fnc_defs[ client->function_index ].result )
{
case rt_number:
isc_putc(' ', client->isc_session);
isc_putul(res->number, client->isc_session);
BUG(("=%lu\n", res->number));
break;
case rt_success:
BUG(("=Success\n"));
break;
case rt_person:
prot_a_output_person(client, &res->person);
BUG(("={Person struct not listed}\n"));
break;
case rt_membership:
prot_a_output_membership(client, &res->membership);
BUG(("={Membership struct not listed}\n"));
break;
case rt_membership_old:
prot_a_output_membership_old(client, &res->membership_old);
BUG(("={Membership_old struct not listed}\n"));
break;
case rt_membership_10:
prot_a_output_membership_10(client, &res->membership_10);
BUG(("={Membership_10 struct not listed}\n"));
break;
case rt_conf_list:
prot_a_output_conf_list(client, res->conf_list);
BUG(("={Conf_list not listed}\n"));
break;
case rt_conf_no_list:
prot_a_output_conf_no_list(client, res->conf_no_list);
BUG(("={Conf_no_list not listed}\n"));
break;
case rt_conference:
prot_a_output_conference(client, &res->conference);
BUG(("={Conference struct not listed}\n"));
break;
case rt_conference_old:
prot_a_output_conference_old(client, &res->conference);
BUG(("={Conference (old) struct not listed}\n"));
break;
case rt_string:
prot_a_output_string(client, res->string);
BUG(("={%luH", res->string.len));
BUGSTR(res->string);
BUG(("}\n"));
break;
case rt_mark_list:
prot_a_output_mark_list(client, res->mark_list);
BUG(("={Mark_list not listed}\n"));
break;
case rt_text_stat_old:
prot_a_output_text_stat_old(client, &res->text_stat);
BUG(("={Text_stat (old) struct not listed}\n"));
break;
case rt_text_stat:
prot_a_output_text_stat(client, &res->text_stat);
BUG(("={Text_stat struct not listed}\n"));
break;
case rt_who_info_list:
prot_a_output_who_info_list(client, res->who_info_list);
BUG(("={Who_info_list not listed}\n"));
break;
case rt_who_info_list_old:
prot_a_output_who_info_list_old(client,
res->who_info_list_old);
BUG(("={Old who_info_list not listed}\n"));
break;
case rt_session_info:
prot_a_output_session_info(client,
&res->session_info);
/* Clear username, since it is allocated (in get_session_info()
in session.c). See comment abover the definition of
union result_holder in connections.h. */
s_clear(&res->session_info.username);
BUG(("={Session_info not listed}\n"));
break;
case rt_info:
prot_a_output_info(client, &res->info);
BUG(("={Who_info struct not listed}\n"));
break;
case rt_info_old:
prot_a_output_info_old(client, &res->info);
BUG(("={Who_info struct not listed}\n"));
break;
case rt_membership_list:
prot_a_output_membership_list(client, res->membership_list);
BUG (("={Membership_list not listed}\n"));
break;
case rt_membership_list_10:
prot_a_output_membership_list_10(client, res->membership_list_10);
BUG (("={Membership_list_10 not listed}\n"));
break;
case rt_membership_list_old:
prot_a_output_membership_list_old (client,
res->membership_list_old);
BUG (("={Membership_list_old not listed}\n"));
break;
case rt_member_list:
prot_a_output_member_list (client, res->member_list);
BUG(("={Member_list not listed}\n"));
break;
case rt_member_list_old:
prot_a_output_member_list_old (client, res->member_list);
BUG(("={Member_list not listed}\n"));
break;
case rt_time_date:
prot_a_output_time (client, res->time_date);
BUG(("=(time_t)%lu\n", (unsigned long)res->time_date));
break;
case rt_session_no:
prot_a_output_session_no (client, res->session_no);
BUG(("=(Session_no)%lu\n", res->session_no));
break;
case rt_text_no:
prot_a_output_text_no (client, res->text_no);
BUG(("=(Text_no)%lu\n", res->text_no));
break;
case rt_who_info_ident_list:
prot_a_output_who_info_ident_list(client,
res->who_info_ident_list);
BUG(("={Who_info_ident_list not listed}\n"));
break;
case rt_session_info_ident:
prot_a_output_session_info_ident(client,
&res->session_info_ident);
BUG(("={Session_info_ident not listed}\n"));
break;
case rt_conf_z_info_list:
prot_a_output_conf_z_info_list(client, res->conf_z_info_list);
BUG(("={Conf_z_info_list not listed}\n"));
break;
case rt_version_info:
prot_a_output_version_info(client, &res->version_info);
BUG(("={Version_info not listed}\n"));
break;
case rt_uconference:
prot_a_output_uconference(client, &res->uconference);
BUG(("={UConference not listed}\n"));
break;
case rt_num_list:
prot_a_output_num_list(client, &res->num_list);
BUG(("={num_list not listed}\n"));
break;
case rt_dynamic_session_info_list:
prot_a_output_dynamic_session_info_list(
client, &res->dynamic_session_info_list);
BUG(("={dynamic_session_list not listed}\n"));
break;
case rt_static_session_info:
prot_a_output_static_session_info(client,
&res->static_session_info);
BUG(("={static_session_info not listed"));
break;
case rt_l2g_iterator_as_text_list:
prot_a_output_l2g_iterator_as_text_list(
client, &res->l2g_iterator_as_text_list);
BUG(("={l2g_iterator_as_text_list not listed"));
break;
case rt_text_mapping:
prot_a_output_text_mapping(client, &res->text_mapping);
BUG(("={text_mapping not listed"));
break;
case rt_stats_description:
prot_a_output_stats_description(client, &res->stats_description);
BUG(("={stats_description not listed"));
break;
case rt_stats_list:
prot_a_output_stats_list(client, &res->stats_list);
BUG(("={stats_list not listed"));
break;
#ifdef DEBUG_CALLS
case rt_memory_info:
prot_a_output_memory_info(client, &res->memory_info);
BUG(("={memory_info not listed"));
break;
#endif
}
isc_putc('\n', client->isc_session);
}
else
{
/* Failure. Give a reply with the error message. */
isc_putc('%', client->isc_session);
isc_putul(client->ref_no, client->isc_session);
prot_a_output_ul(client, kom_errno);
prot_a_output_ul(client, err_stat);
isc_putc('\n', client->isc_session);
BUG(("%%Err %d\n", kom_errno));
}
}
/*
* Set up all data structures that are private to protocol A. This
* function is called from connections.c whenever a connection says
* that it is of type A.
*/
void
prot_a_init(Connection *conn)
{
conn->parse_pos = 0;
conn->fnc_parse_pos = 0;
conn->array_parse_index = 0;
conn->array_parse_parsed_length = 0;
conn->array_parse_pos = 0;
conn->struct_parse_pos = 0;
conn->string_parse_pos = 0;
conn->hunt_parse_pos = 0;
conn->array_hunt_num = 0;
conn->array_hunt_depth = 0;
conn->ref_no = 0;
conn->function = call_fnc_login_old;
conn->function_index = 0;
conn->num0 = 0;
conn->num1 = 0;
conn->num2 = 0;
conn->num3 = 0;
conn->c_string0 = EMPTY_STRING;
conn->c_string1 = EMPTY_STRING;
conn->string0 = EMPTY_STRING;
conn->misc_info_list.misc = NULL;
conn->misc_info_list.no_of_misc = 0;
conn->aux_item_list.items = NULL;
conn->aux_item_list.length = 0;
conn->aux_item.data = EMPTY_STRING;
conn->dummy_aux_item.data = EMPTY_STRING;
conn->c_local_text_no_p = NULL;
init_priv_bits(&conn->priv_bits);
init_conf_type(&conn->conf_type);
}
void
prot_a_destruct(Connection *conn)
{
int i;
/*
* All strings et c should already by free:d - that is done at the
* end of each atomic call. But free them anyhow, just in case
* this client is forced off while unparsed data is present.
*/
s_clear(&conn->string0);
s_clear(&conn->c_string0);
s_clear(&conn->c_string1);
s_clear(&conn->aux_item.data);
s_clear(&conn->dummy_aux_item.data);
for (i = 0; i < conn->aux_item_list.length; i++)
s_clear(&conn->aux_item_list.items[i].data);
conn->aux_item_list.length = 0;
sfree(conn->aux_item_list.items);
conn->aux_item_list.items = NULL;
conn->misc_info_list.no_of_misc = 0;
sfree(conn->misc_info_list.misc);
conn->misc_info_list.misc = NULL;
conn->num_list.length = 0;
sfree(conn->num_list.data);
conn->num_list.data = NULL;
sfree(conn->c_local_text_no_p);
conn->c_local_text_no_p = NULL;
sfree(conn->read_range_list.ranges);
conn->read_range_list.ranges = NULL;
conn->read_range_list.length = 0;
}
/*
* Check if it is a legal function.
*/
static int
prot_a_is_legal_fnc(enum call_header fnc)
{
#include "prot-a-is-legal-fnc.incl"
}
void
prot_a_parse_packet(Connection *client)
{
if ( client->username_valid == FALSE )
{
/* Connection not established yet */
prot_a_parse_string(client, &client->c_string0,
param.username_len);
client->username = client->c_string0; /* Kludge to deal with */
client->c_string0 = EMPTY_STRING; /* "A5B" as first input. */
/* Protokoll B will not suffer from this... */
client->username_valid = TRUE;
isc_puts("LysKOM\n", client->isc_session);
isc_flush(client->isc_session);
isc_set_acceptable_idle(client->isc_session,
param.login_timeout);
BUG(("[Handshake with client %lu completed]\n", client->session_no));
}
if (client->dns_done == FALSE)
{
isc_disable(client->isc_session);
client->blocked_by_dns = TRUE;
return;
}
switch(client->parse_pos)
{
case 0: /* Get ref_no */
/* Delete any leading whitespace. This is not strictly
necessary, as prot_a_parse_long will skip whitespace, but
if we don't get a complete packet this will ensure that the
leading whitespace is discarded now. */
prot_a_parse_skip_whitespace(client);
client->ref_no = prot_a_parse_long(client);
client->parse_pos = 1;
/* Fall through */
case 1: /* Get fnc_no */
client->function = (enum call_header)(int)prot_a_parse_long(client);
if ((client->function_index = prot_a_is_legal_fnc(client->function)) == -1 )
{
client->function = illegal_fnc;
client->function_index = num_fnc_defs - 1;
}
client->parse_pos = 2;
/* Fall through */
case 2:
/* Call the function that parses the arguments for this call. */
(*fnc_defs[client->function_index].parser)(client);
/* Delete any trailing whitespace. */
prot_a_parse_skip_whitespace(client);
/* Fall through */
default:
client->parse_pos = 0;
}
}