--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
/*
- clientutil.c : irssi
- Copyright (C) 2000 Timo Sirainen
+ client.c
- 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; either version 2 of the License, or
- (at your option) any later version.
+ Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
- 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.
+ Copyright (C) 1997 - 2000 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/* $Id$ */
+
+#include "clientincludes.h"
+
+/* Routine used to print lines to window. This can split the
+ line neatly if a word would overlap the line. */
+
+void silc_print_to_window(WINDOW *win, char *message)
+{
+ int str_len, len;
+
+ str_len = strlen(message);
+
+ if (str_len > COLS - 1) {
+ /* Split overlapping words to next line */
+ /* XXX In principal this is wrong as this modifies the original
+ string as it replaces the last ' ' with '\n'. This could be done
+ with little more work so that it would not replace anything. */
+ len = COLS - 1;
+ while (1) {
-#include "module.h"
+ while (len && message[len] != ' ')
+ len--;
-#include "silc-servers.h"
+ if (!len)
+ break;
-/* Verifies received public key. If user decides to trust the key it is
- saved as trusted server key for later use. If user does not trust the
- key this returns FALSE. */
+ message[len] = '\n';
+ len += COLS - 1;
+ if (len > str_len)
+ break;
+ }
+ }
+
+ wprintw(win, "%s", message);
+ wrefresh(win);
+}
-int silc_client_verify_server_key(SILC_SERVER_REC *server,
- unsigned char *pk, unsigned int pk_len,
- SilcSKEPKType pk_type)
+/* Prints message to the screen. This is used to print the messages
+ user is typed and message that came on channels. */
+
+void silc_print(SilcClient client, char *msg, ...)
{
- char filename[256];
- char file[256];
- char *hostname, *fingerprint;
- struct stat st;
+ va_list vp;
+ char message[2048];
+ SilcClientInternal app = client->application;
+
+ memset(message, 0, sizeof(message));
+ strncat(message, "\n ", 2);
+
+ va_start(vp, msg);
+ vsprintf(message + 1, msg, vp);
+ va_end(vp);
+
+ /* Print the message */
+ silc_print_to_window(app->screen->output_win[0], message);
+}
+
+/* Returns user's mail path */
+
+char *silc_get_mail_path()
+{
+ char pathbuf[MAXPATHLEN];
+ char *path;
+
+#ifndef _PATH_MAILDIR
+#define _PATH_MAILDIR "/var/mail"
+#endif
+
+ path = getenv("MAIL");
+ if (path) {
+ strncpy(pathbuf, path, strlen(path));
+ } else {
+ strcpy(pathbuf, _PATH_MAILDIR);
+ strcat(pathbuf, "/");
+ strcat(pathbuf, silc_get_username());
+ }
+
+ return strdup(pathbuf);
+}
+
+/* gets the number of the user's mails, if possible */
+
+int silc_get_number_of_emails()
+{
+ FILE *tl;
+ int num = 0;
+ char *filename;
+ char data[1024];
+
+ filename = silc_get_mail_path();
+
+ tl = fopen(filename, "r");
+ if (!tl) {
+ fprintf(stderr, "Couldn't open mail file (%s).\n", filename);
+ } else {
+ while((fscanf(tl, "%s", data)) != EOF) {
+ if(!strcmp(data, "From:"))
+ num++;
+ }
+
+ fclose(tl);
+ }
+
+ return num;
+}
+
+/* Returns time til next minute changes. Used to update the clock when
+ needed. */
+
+int silc_client_time_til_next_min()
+{
+ time_t curtime;
+ struct tm *min;
+
+ curtime = time(0);
+ min = localtime(&curtime);
+
+ return 60 - min->tm_sec;
+}
+
+/* Asks yes/no from user on the input line. Returns TRUE on "yes" and
+ FALSE on "no". */
+
+int silc_client_ask_yes_no(SilcClient client, char *prompt)
+{
+ SilcClientInternal app = (SilcClientInternal)client->application;
+ char answer[4];
+ int ret;
+
+ again:
+ silc_screen_input_reset(app->screen);
+
+ /* Print prompt */
+ wattroff(app->screen->input_win, A_INVIS);
+ silc_screen_input_print_prompt(app->screen, prompt);
+
+ /* Get string */
+ memset(answer, 0, sizeof(answer));
+ echo();
+ wgetnstr(app->screen->input_win, answer, sizeof(answer));
+ if (!strncasecmp(answer, "yes", strlen(answer)) ||
+ !strncasecmp(answer, "y", strlen(answer))) {
+ ret = TRUE;
+ } else if (!strncasecmp(answer, "no", strlen(answer)) ||
+ !strncasecmp(answer, "n", strlen(answer))) {
+ ret = FALSE;
+ } else {
+ silc_say(client, app->conn, "Type yes or no");
+ goto again;
+ }
+ noecho();
+
+ silc_screen_input_reset(app->screen);
+
+ return ret;
+}
+
+/* Lists supported (builtin) ciphers */
+
+void silc_client_list_ciphers()
+{
+ char *ciphers = silc_cipher_get_supported();
+ fprintf(stdout, "%s\n", ciphers);
+ silc_free(ciphers);
+}
+
+/* Lists supported (builtin) hash functions */
+
+void silc_client_list_hash_funcs()
+{
+ char *hash = silc_hash_get_supported();
+ fprintf(stdout, "%s\n", hash);
+ silc_free(hash);
+}
+
+/* Lists supported PKCS algorithms */
+
+void silc_client_list_pkcs()
+{
+ char *pkcs = silc_pkcs_get_supported();
+ fprintf(stdout, "%s\n", pkcs);
+ silc_free(pkcs);
+}
+
+/* Displays input prompt on command line and takes input data from user */
+
+char *silc_client_get_input(const char *prompt)
+{
+ char input[2048];
+ int fd;
+
+ fd = open("/dev/tty", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "silc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ memset(input, 0, sizeof(input));
+
+ printf("%s", prompt);
+ fflush(stdout);
+
+ if ((read(fd, input, sizeof(input))) < 0) {
+ fprintf(stderr, "silc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ if (strlen(input) <= 1)
+ return NULL;
+
+ if (strchr(input, '\n'))
+ *strchr(input, '\n') = '\0';
+
+ return strdup(input);
+}
+
+/* Displays prompt on command line and takes passphrase with echo
+ off from user. */
+
+char *silc_client_get_passphrase(const char *prompt)
+{
+#if 0
+ char input[2048];
+ char *ret;
+ int fd;
+ struct termios to;
+ struct termios to_old;
+
+ fd = open("/dev/tty", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "silc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ signal(SIGINT, SIG_IGN);
+
+ /* Get terminal info */
+ tcgetattr(fd, &to);
+ to_old = to;
+
+ /* Echo OFF */
+ to.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ tcsetattr(fd, TCSANOW, &to);
+
+ memset(input, 0, sizeof(input));
+
+ printf("%s", prompt);
+ fflush(stdout);
+
+ if ((read(fd, input, sizeof(input))) < 0) {
+ fprintf(stderr, "silc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ if (strlen(input) <= 1) {
+ tcsetattr(fd, TCSANOW, &to_old);
+ return NULL;
+ }
+
+ if (strchr(input, '\n'))
+ *strchr(input, '\n') = '\0';
+
+ /* Restore old terminfo */
+ tcsetattr(fd, TCSANOW, &to_old);
+ signal(SIGINT, SIG_DFL);
+
+ ret = silc_calloc(strlen(input), sizeof(char));
+ memcpy(ret, input, strlen(input));
+ memset(input, 0, sizeof(input));
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+/* Returns identifier string for public key generation. */
+
+char *silc_client_create_identifier()
+{
+ char *username = NULL, *realname = NULL;
+ char hostname[256], email[256];
+
+ /* Get realname */
+ realname = silc_get_real_name();
+
+ /* Get hostname */
+ memset(hostname, 0, sizeof(hostname));
+ gethostname(hostname, sizeof(hostname));
+
+ /* Get username (mandatory) */
+ username = silc_get_username();
+ if (!username)
+ return NULL;
+
+ /* Create default email address, whether it is right or not */
+ snprintf(email, sizeof(email), "%s@%s", username, hostname);
+
+ return silc_pkcs_encode_identifier(username, hostname, realname, email,
+ NULL, NULL);
+}
+
+/* Creates new public key and private key pair. This is used only
+ when user wants to create new key pair from command line. */
+
+int silc_client_create_key_pair(char *pkcs_name, int bits,
+ char *public_key, char *private_key,
+ char *identifier,
+ SilcPublicKey *ret_pub_key,
+ SilcPrivateKey *ret_prv_key)
+{
+ SilcPKCS pkcs;
+ SilcPublicKey pub_key;
+ SilcPrivateKey prv_key;
+ SilcRng rng;
+ unsigned char *key;
+ uint32 key_len;
+ char line[256];
+ char *pkfile = NULL, *prvfile = NULL;
+
+ if (!pkcs_name || !public_key || !private_key)
+ printf("\
+New pair of keys will be created. Please, answer to following questions.\n\
+");
- hostname = server->connrec->address;
+ if (!pkcs_name) {
+ again_name:
+ pkcs_name =
+ silc_client_get_input("PKCS name (l to list names) [rsa]: ");
+ if (!pkcs_name)
+ pkcs_name = strdup("rsa");
- if (pk_type != SILC_SKE_PK_TYPE_SILC) {
- //silc_say(client, "We don't support server %s key type", hostname);
+ if (*pkcs_name == 'l' || *pkcs_name == 'L') {
+ silc_client_list_pkcs();
+ silc_free(pkcs_name);
+ goto again_name;
+ }
+ }
+
+ if (!silc_pkcs_is_supported(pkcs_name)) {
+ fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
return FALSE;
}
+ if (!bits) {
+ char *length = NULL;
+ length =
+ silc_client_get_input("Key length in bits [1024]: ");
+ if (!length)
+ bits = 1024;
+ else
+ bits = atoi(length);
+ }
+
+ if (!identifier) {
+ char *def = silc_client_create_identifier();
+
+ memset(line, 0, sizeof(line));
+ if (def)
+ snprintf(line, sizeof(line), "Identifier [%s]: ", def);
+ else
+ snprintf(line, sizeof(line),
+ "Identifier (eg. UN=jon, HN=jon.dummy.com, "
+ "RN=Jon Johnson, E=jon@dummy.com): ");
+
+ while (!identifier) {
+ identifier = silc_client_get_input(line);
+ if (!identifier && def)
+ identifier = strdup(def);
+ }
+
+ if (def)
+ silc_free(def);
+ }
+
+ rng = silc_rng_alloc();
+ silc_rng_init(rng);
+ silc_rng_global_init(rng);
+
+ if (!public_key) {
+ memset(line, 0, sizeof(line));
+ snprintf(line, sizeof(line), "Public key filename [%s] ",
+ SILC_CLIENT_PUBLIC_KEY_NAME);
+ pkfile = silc_client_get_input(line);
+ if (!pkfile)
+ pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
+ } else {
+ pkfile = public_key;
+ }
+
+ if (!private_key) {
+ memset(line, 0, sizeof(line));
+ snprintf(line, sizeof(line), "Public key filename [%s] ",
+ SILC_CLIENT_PRIVATE_KEY_NAME);
+ prvfile = silc_client_get_input(line);
+ if (!prvfile)
+ prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
+ } else {
+ prvfile = private_key;
+ }
+
+ /* Generate keys */
+ silc_pkcs_alloc(pkcs_name, &pkcs);
+ pkcs->pkcs->init(pkcs->context, bits, rng);
+
+ /* Save public key into file */
+ key = silc_pkcs_get_public_key(pkcs, &key_len);
+ pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
+ key, key_len);
+ silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
+ if (ret_pub_key)
+ *ret_pub_key = pub_key;
+
+ memset(key, 0, sizeof(key_len));
+ silc_free(key);
+
+ /* Save private key into file */
+ key = silc_pkcs_get_private_key(pkcs, &key_len);
+ prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
+
+ silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
+ if (ret_prv_key)
+ *ret_prv_key = prv_key;
+
+ printf("Public key has been saved into `%s'.\n", pkfile);
+ printf("Private key has been saved into `%s'.\n", prvfile);
+ printf("Press <Enter> to continue...\n");
+ getchar();
+
+ memset(key, 0, sizeof(key_len));
+ silc_free(key);
+
+ silc_rng_free(rng);
+ silc_pkcs_free(pkcs);
+
+ return TRUE;
+}
+
+/* This checks stats for various SILC files and directories. First it
+ checks if ~/.silc directory exist and is owned by the correct user. If
+ it doesn't exist, it will create the directory. After that it checks if
+ user's Public and Private key files exists and that they aren't expired.
+ If they doesn't exist or they are expired, they will be (re)created
+ after return. */
+
+int silc_client_check_silc_dir()
+{
+ char filename[256], file_public_key[256], file_private_key[256];
+ char servfilename[256], clientfilename[256];
+ char *identifier;
+ struct stat st;
+ struct passwd *pw;
+ int firstime = FALSE;
+ time_t curtime, modtime;
+
+ SILC_LOG_DEBUG(("Checking ~./silc directory"));
+
memset(filename, 0, sizeof(filename));
- memset(file, 0, sizeof(file));
- snprintf(file, sizeof(file) - 1, "serverkey_%s_%d.pub", hostname,
- server->connrec->port);
- snprintf(filename, sizeof(filename) - 1, "%s/.silc/serverkeys/%s",
- g_get_home_dir(), file);
-
- /* Check wheter this key already exists */
- if (stat(filename, &st) < 0) {
-
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- /*silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);*/
- silc_free(fingerprint);
-
- /* Ask user to verify the key and save it */
- /*if (silc_client_ask_yes_no(client,
- "Would you like to accept the key (y/n)? "))*/
- {
- /* Save the key for future checking */
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
+ memset(file_public_key, 0, sizeof(file_public_key));
+ memset(file_private_key, 0, sizeof(file_private_key));
+
+ pw = getpwuid(getuid());
+ if (!pw) {
+ fprintf(stderr, "silc: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ identifier = silc_client_create_identifier();
+
+ /* We'll take home path from /etc/passwd file to be sure. */
+ snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
+ snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
+ pw->pw_dir);
+ snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
+ pw->pw_dir);
+
+ /*
+ * Check ~/.silc directory
+ */
+ if ((stat(filename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((mkdir(filename, 0755)) == -1) {
+ fprintf(stderr, "Couldn't create `%s' directory\n", filename);
+ return FALSE;
+ }
+
+ /* Directory was created. First time running SILC */
+ firstime = TRUE;
+ } else {
+ fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+ filename);
+ return FALSE;
}
+ } else {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return FALSE;
+ }
} else {
- /* The key already exists, verify it. */
- SilcPublicKey public_key;
- unsigned char *encpk;
- unsigned int encpk_len;
-
- /* Load the key file */
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_PEM))
- if (!silc_pkcs_load_public_key(filename, &public_key,
- SILC_PKCS_FILE_BIN)) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- /*silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);*/
- silc_free(fingerprint);
- /*silc_say(client, "Could not load your local copy of the server %s key",
- hostname);
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))*/
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
-
+
+ /* Check the owner of the dir */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ fprintf(stderr, "You don't seem to own `%s' directory\n",
+ filename);
+ return FALSE;
+ }
+
+ /* Check the permissions of the dir */
+ if ((st.st_mode & 0777) != 0755) {
+ if ((chmod(filename, 0755)) == -1) {
+ fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
+ filename);
return FALSE;
}
+ }
+ }
+
+ /*
+ * Check ~./silc/serverkeys directory
+ */
+ if ((stat(servfilename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((mkdir(servfilename, 0755)) == -1) {
+ fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
+ return FALSE;
+ }
+ } else {
+ fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+ servfilename);
+ return FALSE;
+ }
+ } else {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return FALSE;
+ }
+ }
- /* Encode the key data */
- encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
- if (!encpk) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- /*silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);*/
- silc_free(fingerprint);
- /*silc_say(client, "Your local copy of the server %s key is malformed",
- hostname);
- if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))*/
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
+ /*
+ * Check ~./silc/clientkeys directory
+ */
+ if ((stat(clientfilename, &st)) == -1) {
+ /* If dir doesn't exist */
+ if (errno == ENOENT) {
+ if (pw->pw_uid == geteuid()) {
+ if ((mkdir(clientfilename, 0755)) == -1) {
+ fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
+ return FALSE;
}
+ } else {
+ fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+ clientfilename);
+ return FALSE;
+ }
+ } else {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check Public and Private keys
+ */
+ snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
+ filename, SILC_CLIENT_PUBLIC_KEY_NAME);
+ snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
+ filename, SILC_CLIENT_PRIVATE_KEY_NAME);
+
+ /* If running SILC first time */
+ if (firstime) {
+ fprintf(stdout, "Running SILC for the first time\n");
+ silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
+ SILC_CLIENT_DEF_PKCS_LEN,
+ file_public_key, file_private_key,
+ identifier, NULL, NULL);
+ return TRUE;
+ }
+
+ if ((stat(file_public_key, &st)) == -1) {
+ /* If file doesn't exist */
+ if (errno == ENOENT) {
+ fprintf(stdout, "Your public key doesn't exist\n");
+ silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
+ SILC_CLIENT_DEF_PKCS_LEN,
+ file_public_key,
+ file_private_key, identifier, NULL, NULL);
+ } else {
+ fprintf(stderr, "%s\n", strerror(errno));
+ return FALSE;
+ }
+ }
+ if ((stat(file_private_key, &st)) == -1) {
+ /* If file doesn't exist */
+ if (errno == ENOENT) {
+ fprintf(stdout, "Your private key doesn't exist\n");
+ silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
+ SILC_CLIENT_DEF_PKCS_LEN,
+ file_public_key,
+ file_private_key, identifier, NULL, NULL);
+ } else {
+ fprintf(stderr, "%s\n", strerror(errno));
return FALSE;
}
+ }
+
+ /* Check the owner of the public key */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ fprintf(stderr, "You don't seem to own your public key!?\n");
+ return FALSE;
+ }
+
+ /* Check the owner of the private key */
+ if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+ fprintf(stderr, "You don't seem to own your private key!?\n");
+ return FALSE;
+ }
+
+ /* Check the permissions for the private key */
+ if ((st.st_mode & 0777) != 0600) {
+ fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
+ "Trying to change them ... ", file_private_key);
+ if ((chmod(file_private_key, 0600)) == -1) {
+ fprintf(stderr,
+ "Failed to change permissions for private key file!\n"
+ "Permissions for your private key file must be 0600.\n");
+ return FALSE;
+ }
+ fprintf(stderr, "Done.\n\n");
+ }
- if (memcmp(encpk, pk, encpk_len)) {
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- /*silc_say(client, "Received server %s public key", hostname);
- silc_say(client, "Fingerprint for the server %s key is", hostname);
- silc_say(client, "%s", fingerprint);*/
- silc_free(fingerprint);
- /*silc_say(client, "Server %s key does not match with your local copy",
- hostname);
- silc_say(client, "It is possible that the key has expired or changed");
- silc_say(client, "It is also possible that some one is performing "
- "man-in-the-middle attack");*/
-
- /* Ask user to verify the key and save it */
- /*if (silc_client_ask_yes_no(client,
- "Would you like to accept the key anyway (y/n)? "))*/
- {
- /* Save the key for future checking */
- unlink(filename);
- silc_pkcs_save_public_key_data(filename, pk, pk_len,
- SILC_PKCS_FILE_PEM);
- return TRUE;
- }
+ /* See if the key has expired. */
+ modtime = st.st_mtime; /* last modified */
+ curtime = time(0) - modtime;
+
+ /* 86400 is seconds in a day. */
+ if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
+ fprintf(stdout,
+ "--------------------------------------------------\n"
+ "Your private key has expired and needs to be\n"
+ "recreated. This will be done automatically now.\n"
+ "Your new key will expire in %d days from today.\n"
+ "--------------------------------------------------\n",
+ SILC_CLIENT_KEY_EXPIRES);
+
+ silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
+ SILC_CLIENT_DEF_PKCS_LEN,
+ file_public_key,
+ file_private_key, identifier, NULL, NULL);
+ }
+
+ if (identifier)
+ silc_free(identifier);
+
+ return TRUE;
+}
+
+/* Loads public and private key from files. */
+
+int silc_client_load_keys(SilcClient client)
+{
+ char filename[256];
+ struct passwd *pw;
+
+ SILC_LOG_DEBUG(("Loading public and private keys"));
+
+ pw = getpwuid(getuid());
+ if (!pw)
+ return FALSE;
+
+ memset(filename, 0, sizeof(filename));
+ snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
+ pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
+
+ if (silc_pkcs_load_private_key(filename, &client->private_key,
+ SILC_PKCS_FILE_BIN) == FALSE)
+ if (silc_pkcs_load_private_key(filename, &client->private_key,
+ SILC_PKCS_FILE_PEM) == FALSE)
+ return FALSE;
+
+ memset(filename, 0, sizeof(filename));
+ snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
+ pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
- //silc_say(client, "Will not accept server %s key", hostname);
+ if (silc_pkcs_load_public_key(filename, &client->public_key,
+ SILC_PKCS_FILE_PEM) == FALSE)
+ if (silc_pkcs_load_public_key(filename, &client->public_key,
+ SILC_PKCS_FILE_BIN) == FALSE)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Dumps the public key on screen. Used from the command line option. */
+
+int silc_client_show_key(char *keyfile)
+{
+ SilcPublicKey public_key;
+ SilcPublicKeyIdentifier ident;
+ char *fingerprint;
+ unsigned char *pk;
+ uint32 pk_len;
+ SilcPKCS pkcs;
+ int key_len = 0;
+
+ if (silc_pkcs_load_public_key(keyfile, &public_key,
+ SILC_PKCS_FILE_PEM) == FALSE)
+ if (silc_pkcs_load_public_key(keyfile, &public_key,
+ SILC_PKCS_FILE_BIN) == FALSE) {
+ fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
return FALSE;
}
- /* Local copy matched */
- return TRUE;
+ ident = silc_pkcs_decode_identifier(public_key->identifier);
+
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+
+ if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+ key_len = silc_pkcs_public_key_set(pkcs, public_key);
+ silc_pkcs_free(pkcs);
}
- //silc_say(client, "Will not accept server %s key", hostname);
- return FALSE;
+ printf("Public key file : %s\n", keyfile);
+ printf("Algorithm : %s\n", public_key->name);
+ if (key_len)
+ printf("Key length (bits) : %d\n", key_len);
+ if (ident->realname)
+ printf("Real name : %s\n", ident->realname);
+ if (ident->username)
+ printf("Username : %s\n", ident->username);
+ if (ident->host)
+ printf("Hostname : %s\n", ident->host);
+ if (ident->email)
+ printf("Email : %s\n", ident->email);
+ if (ident->org)
+ printf("Organization : %s\n", ident->org);
+ if (ident->country)
+ printf("Country : %s\n", ident->country);
+ printf("Fingerprint (SHA1) : %s\n", fingerprint);
+
+ fflush(stdout);
+
+ silc_free(fingerprint);
+ silc_free(pk);
+ silc_pkcs_public_key_free(public_key);
+ silc_pkcs_free_identifier(ident);
+
+ return TRUE;
}
-#ifndef __CLIENTUTIL_H
-#define __CLIENTUTIL_H
+/*
-int silc_client_verify_server_key(SILC_SERVER_REC *server,
- unsigned char *pk, unsigned int pk_len,
- SilcSKEPKType pk_type);
+ client.h
+
+ Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ Copyright (C) 1997 - 2000 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+*/
+
+#ifndef CLIENTUTIL_H
+#define CLIENTUTIL_H
+
+/* Prototypes */
+void silc_print_to_window(WINDOW *win, char *message);
+void silc_print(SilcClient client, char *msg, ...);
+char *silc_get_mail_path();
+int silc_get_number_of_emails();
+int silc_client_time_til_next_min();
+int silc_client_ask_yes_no(SilcClient client, char *prompt);
+char *silc_client_get_input(const char *prompt);
+char *silc_client_get_passphrase(const char *prompt);
+void silc_client_list_ciphers();
+void silc_client_list_hash_funcs();
+void silc_client_list_pkcs();
+char *silc_client_create_identifier();
+int silc_client_create_key_pair(char *pkcs_name, int bits,
+ char *public_key, char *private_key,
+ char *identifier,
+ SilcPublicKey *ret_pub_key,
+ SilcPrivateKey *ret_prv_key);
+int silc_client_check_silc_dir();
+int silc_client_load_keys(SilcClient client);
+int silc_client_show_key(char *keyfile);
#endif
+/*
+
+ silc-core.c
+
+ Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ Copyright (C) 2001 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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.
+
+*/
+
#include "module.h"
#include "chat-protocols.h"
#include "fe-common/core/printtext.h"
#include "fe-common/core/fe-channels.h"
-#define SILC_CLIENT_PUBLIC_KEY_NAME "public_key.pub"
-#define SILC_CLIENT_PRIVATE_KEY_NAME "private_key.prv"
-
-#define SILC_CLIENT_DEF_PKCS "rsa"
-#define SILC_CLIENT_DEF_PKCS_LEN 1024
-
-SilcClient silc_client;
-const char *silc_version_string = SILC_PROTOCOL_VERSION_STRING;
+/* Command line option variables */
+static char *opt_server = NULL;
+static int opt_port = 0;
+static char *opt_nickname = NULL;
+static char *opt_channel = NULL;
+static char *opt_cipher = NULL;
+static char *opt_public_key = NULL;
+static char *opt_private_key = NULL;
+static char *opt_config_file = NULL;
+static bool opt_no_silcrc = FALSE;
+
+static bool opt_create_keypair = FALSE;
+static char *opt_pkcs = NULL;
+static char *opt_keyfile = NULL;
+static int opt_bits = 0;
static int idletag;
-
+static SilcClient silc_client;
extern SilcClientOperations ops;
static void silc_say(SilcClient client, SilcClientConnection conn,
char *msg, ...)
{
- SILC_SERVER_REC *server;
- va_list va;
- char *str;
-
- server = conn == NULL ? NULL : conn->context;
-
- va_start(va, msg);
- str = g_strdup_vprintf(msg, va);
- printtext(server, "#silc", MSGLEVEL_CRAP, "%s", str);
- g_free(str);
- va_end(va);
+ SILC_SERVER_REC *server;
+ va_list va;
+ char *str;
+
+ server = conn == NULL ? NULL : conn->context;
+
+ va_start(va, msg);
+ str = g_strdup_vprintf(msg, va);
+ printtext(server, "#silc", MSGLEVEL_CRAP, "%s", str);
+ g_free(str);
+ va_end(va);
}
-static void silc_channel_message(SilcClient c, SilcClientConnection conn,
- SilcClientEntry client,
- SilcChannelEntry channel, char *msg)
+/* Message for a channel. The `sender' is the nickname of the sender
+ received in the packet. The `channel_name' is the name of the channel. */
+
+static void
+silc_channel_message(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry sender, SilcChannelEntry channel,
+ SilcMessageFlags flags, char *msg)
{
- SILC_SERVER_REC *server;
- SILC_NICK_REC *nick;
- SILC_CHANNEL_REC *chanrec;
-
- server = conn == NULL ? NULL : conn->context;
- chanrec = silc_channel_find_entry(server, channel);
-
- nick = client == NULL ? NULL : silc_nicklist_find(chanrec, client);
- signal_emit("message public", 6, server, msg,
- nick == NULL ? "(unknown)" : nick->nick,
- nick == NULL ? NULL : nick->host,
- chanrec->name, nick);
+ SILC_SERVER_REC *server;
+ SILC_NICK_REC *nick;
+ SILC_CHANNEL_REC *chanrec;
+
+ server = conn == NULL ? NULL : conn->context;
+ chanrec = silc_channel_find_entry(server, channel);
+
+ nick = silc_nicklist_find(chanrec, sender);
+ signal_emit("message public", 6, server, msg,
+ nick == NULL ? "(unknown)" : nick->nick,
+ nick == NULL ? NULL : nick->host,
+ chanrec->name, nick);
}
-static void silc_private_message(SilcClient c, SilcClientConnection conn,
- SilcClientEntry client, char *msg)
-{
- SILC_SERVER_REC *server;
+/* Private message to the client. The `sender' is the nickname of the
+ sender received in the packet. */
- server = conn == NULL ? NULL : conn->context;
- signal_emit("message private", 4, server, msg,
- client == NULL ? "(unknown)" : client->nickname,
- client == NULL ? NULL : client->username);
+static void
+silc_private_message(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry sender, SilcMessageFlags flags,
+ char *msg)
+{
+ SILC_SERVER_REC *server;
+
+ server = conn == NULL ? NULL : conn->context;
+ signal_emit("message private", 4, server, msg,
+ sender->nickname ? sender->nickname : "(unknown)",
+ sender->username ? sender->username : NULL);
}
+/* Notify message to the client. The notify arguments are sent in the
+ same order as servers sends them. The arguments are same as received
+ from the server except for ID's. If ID is received application receives
+ the corresponding entry to the ID. For example, if Client ID is received
+ application receives SilcClientEntry. Also, if the notify type is
+ for channel the channel entry is sent to application (even if server
+ does not send it). */
+
typedef struct {
- int type;
- const char *name;
+ int type;
+ const char *name;
} NOTIFY_REC;
#define MAX_NOTIFY (sizeof(notifies)/sizeof(notifies[0]))
static NOTIFY_REC notifies[] = {
- { SILC_NOTIFY_TYPE_NONE, NULL },
- { SILC_NOTIFY_TYPE_INVITE, "invite" },
- { SILC_NOTIFY_TYPE_JOIN, "join" },
- { SILC_NOTIFY_TYPE_LEAVE, "leave" },
- { SILC_NOTIFY_TYPE_SIGNOFF, "signoff" },
- { SILC_NOTIFY_TYPE_TOPIC_SET, "topic" },
- { SILC_NOTIFY_TYPE_NICK_CHANGE, "nick" },
- { SILC_NOTIFY_TYPE_CMODE_CHANGE, "cmode" },
- { SILC_NOTIFY_TYPE_CUMODE_CHANGE, "cumode" },
- { SILC_NOTIFY_TYPE_MOTD, "motd" }
+ { SILC_NOTIFY_TYPE_NONE, NULL },
+ { SILC_NOTIFY_TYPE_INVITE, "invite" },
+ { SILC_NOTIFY_TYPE_JOIN, "join" },
+ { SILC_NOTIFY_TYPE_LEAVE, "leave" },
+ { SILC_NOTIFY_TYPE_SIGNOFF, "signoff" },
+ { SILC_NOTIFY_TYPE_TOPIC_SET, "topic" },
+ { SILC_NOTIFY_TYPE_NICK_CHANGE, "nick" },
+ { SILC_NOTIFY_TYPE_CMODE_CHANGE, "cmode" },
+ { SILC_NOTIFY_TYPE_CUMODE_CHANGE, "cumode" },
+ { SILC_NOTIFY_TYPE_MOTD, "motd" }
};
static void silc_notify(SilcClient client, SilcClientConnection conn,
- SilcNotifyType type, ...)
+ SilcNotifyType type, ...)
{
- SILC_SERVER_REC *server;
- va_list va;
-
- server = conn == NULL ? NULL : conn->context;
- va_start(va, type);
-
- if (type == SILC_NOTIFY_TYPE_NONE) {
- /* some generic notice from server */
- printtext(server, NULL, MSGLEVEL_CRAP, "%s",
- (char *) va_arg(va, char *));
- } else if (type < MAX_NOTIFY) {
- /* send signal about the notify event */
- char signal[50];
-
- g_snprintf(signal, sizeof(signal), "silc event %s",
- notifies[type].name);
- signal_emit(signal, 2, server, va);
- } else {
- /* unknown notify */
- printtext(server, NULL, MSGLEVEL_CRAP,
- "Unknown notify %d", type);
- }
- va_end(va);
+ SILC_SERVER_REC *server;
+ va_list va;
+
+ server = conn == NULL ? NULL : conn->context;
+ va_start(va, type);
+
+ if (type == SILC_NOTIFY_TYPE_NONE) {
+ /* some generic notice from server */
+ printtext(server, NULL, MSGLEVEL_CRAP, "%s",
+ (char *) va_arg(va, char *));
+ } else if (type < MAX_NOTIFY) {
+ /* send signal about the notify event */
+ char signal[50];
+
+ g_snprintf(signal, sizeof(signal), "silc event %s",
+ notifies[type].name);
+ signal_emit(signal, 2, server, va);
+ } else {
+ /* unknown notify */
+ printtext(server, NULL, MSGLEVEL_CRAP,
+ "Unknown notify %d", type);
+ }
+ va_end(va);
}
-static void silc_connect(SilcClient client, SilcClientConnection conn, int success)
-{
- SILC_SERVER_REC *server = conn->context;
+/* 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. */
- if (success) {
- server->connected = TRUE;
- signal_emit("event connected", 1, server);
- } else {
- server->connection_lost = TRUE;
- server->conn->context = NULL;
- server_disconnect(SERVER(server));
- }
+static void
+silc_connect(SilcClient client, SilcClientConnection conn, int success)
+{
+ SILC_SERVER_REC *server = conn->context;
+
+ if (success) {
+ server->connected = TRUE;
+ signal_emit("event connected", 1, server);
+ } else {
+ server->connection_lost = TRUE;
+ server->conn->context = NULL;
+ server_disconnect(SERVER(server));
+ }
}
-static void silc_disconnect(SilcClient client, SilcClientConnection conn)
+/* Called to indicate that connection was disconnected to the server. */
+
+static void
+silc_disconnect(SilcClient client, SilcClientConnection conn)
{
SILC_SERVER_REC *server = conn->context;
server_disconnect(SERVER(server));
}
-static void silc_command(SilcClient client, SilcClientConnection conn,
- SilcClientCommandContext cmd_context, int success,
- SilcCommand command)
+/* Command handler. This function is called always in the command function.
+ If error occurs it will be called as well. `conn' is the associated
+ client connection. `cmd_context' is the command context that was
+ originally sent to the command. `success' is FALSE if error occured
+ during command. `command' is the command being processed. It must be
+ noted that this is not reply from server. This is merely called just
+ after application has called the command. Just to tell application
+ that the command really was processed. */
+
+static void
+silc_command(SilcClient client, SilcClientConnection conn,
+ SilcClientCommandContext cmd_context, int success,
+ SilcCommand command)
{
}
-static void silc_command_reply(SilcClient client, SilcClientConnection conn,
- SilcCommandPayload cmd_payload, int success,
- SilcCommand command,
- SilcCommandStatus status, ...)
+/* Command reply handler. This function is called always in the command reply
+ function. If error occurs it will be called as well. Normal scenario
+ is that it will be called after the received command data has been parsed
+ and processed. The function is used to pass the received command data to
+ the application.
+
+ `conn' is the associated client connection. `cmd_payload' is the command
+ payload data received from server and it can be ignored. It is provided
+ if the application would like to re-parse the received command data,
+ however, it must be noted that the data is parsed already by the library
+ thus the payload can be ignored. `success' is FALSE if error occured.
+ In this case arguments are not sent to the application. `command' is the
+ command reply being processed. The function has variable argument list
+ and each command defines the number and type of arguments it passes to the
+ application (on error they are not sent). */
+
+static void
+silc_command_reply(SilcClient client, SilcClientConnection conn,
+ SilcCommandPayload cmd_payload, int success,
+ SilcCommand command, SilcCommandStatus status, ...)
+
{
- SILC_SERVER_REC *server = conn->context;
- SILC_CHANNEL_REC *chanrec;
- va_list va;
-
- va_start(va, status);
-
- /*g_snprintf(signal, sizeof(signal), "silc command reply %s",
- silc_commands[type]);
- signal_emit(signal, 2, server, va);*/
-
- switch(command) {
- case SILC_COMMAND_JOIN: {
- char *channel, *mode;
-
- channel = va_arg(va, char *);
- (void)va_arg(va, SilcChannelEntry);
- mode = silc_client_chmode(va_arg(va, unsigned int));
-
- chanrec = silc_channel_find(server, channel);
- if (chanrec != NULL && !success)
- channel_destroy(CHANNEL(chanrec));
- else if (chanrec == NULL && success)
- chanrec = silc_channel_create(server, channel, TRUE);
-
- g_free_not_null(chanrec->mode);
- chanrec->mode = g_strdup(mode == NULL ? "" : mode);
- signal_emit("channel mode changed", 1, chanrec);
- break;
- }
- case SILC_COMMAND_NICK: {
- SilcClientEntry client = va_arg(va, SilcClientEntry);
- char *old;
-
- old = g_strdup(server->nick);
- server_change_nick(SERVER(server), client->nickname);
- nicklist_rename_unique(SERVER(server),
- server->conn->local_entry, server->nick,
- client, client->nickname);
-
- signal_emit("message own_nick", 4,
- server, server->nick, old, "");
- g_free(old);
- break;
- }
- case SILC_COMMAND_USERS: {
- SilcChannelEntry channel;
- SilcChannelUser user;
- NICK_REC *ownnick;
-
- channel = va_arg(va, SilcChannelEntry);
- chanrec = silc_channel_find_entry(server, channel);
- if (chanrec == NULL)
- break;
-
- silc_list_start(channel->clients);
- while ((user = silc_list_get(channel->clients)) != NULL)
- silc_nicklist_insert(chanrec, user, FALSE);
-
- ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
- nicklist_set_own(CHANNEL(chanrec), ownnick);
- signal_emit("channel joined", 1, chanrec);
- fe_channels_nicklist(CHANNEL(chanrec),
- CHANNEL_NICKLIST_FLAG_ALL);
- break;
- }
- }
-
- va_end(va);
+ SILC_SERVER_REC *server = conn->context;
+ SILC_CHANNEL_REC *chanrec;
+ va_list va;
+
+ va_start(va, status);
+
+ /*g_snprintf(signal, sizeof(signal), "silc command reply %s",
+ silc_commands[type]);
+ signal_emit(signal, 2, server, va);*/
+
+ switch(command) {
+ case SILC_COMMAND_JOIN:
+ {
+ char *channel, *mode;
+ uint32 modei;
+ SilcChannelEntry channel_entry;
+
+ channel = va_arg(va, char *);
+ channel_entry = va_arg(va, SilcChannelEntry);
+ modei = va_arg(va, uint32);
+ mode = silc_client_chmode(modei, channel_entry);
+
+ chanrec = silc_channel_find(server, channel);
+ if (chanrec != NULL && !success)
+ channel_destroy(CHANNEL(chanrec));
+ else if (chanrec == NULL && success)
+ chanrec = silc_channel_create(server, channel, TRUE);
+
+ g_free_not_null(chanrec->mode);
+ chanrec->mode = g_strdup(mode == NULL ? "" : mode);
+ signal_emit("channel mode changed", 1, chanrec);
+ break;
+ }
+ case SILC_COMMAND_NICK:
+ {
+ SilcClientEntry client = va_arg(va, SilcClientEntry);
+ char *old;
+
+ old = g_strdup(server->nick);
+ server_change_nick(SERVER(server), client->nickname);
+ nicklist_rename_unique(SERVER(server),
+ server->conn->local_entry, server->nick,
+ client, client->nickname);
+
+ signal_emit("message own_nick", 4,
+ server, server->nick, old, "");
+ g_free(old);
+ break;
+ }
+ case SILC_COMMAND_USERS:
+ {
+ SilcChannelEntry channel;
+ SilcChannelUser user;
+ NICK_REC *ownnick;
+
+ channel = va_arg(va, SilcChannelEntry);
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec == NULL)
+ break;
+
+ silc_list_start(channel->clients);
+ while ((user = silc_list_get(channel->clients)) != NULL)
+ silc_nicklist_insert(chanrec, user, FALSE);
+
+ ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
+ nicklist_set_own(CHANNEL(chanrec), ownnick);
+ signal_emit("channel joined", 1, chanrec);
+ fe_channels_nicklist(CHANNEL(chanrec),
+ CHANNEL_NICKLIST_FLAG_ALL);
+ break;
+ }
+ }
+
+ va_end(va);
}
-static int silc_verify_server_key(SilcClient client, SilcClientConnection conn,
- unsigned char *pk, unsigned int pk_len,
+/* Verifies received public key. If user decides to trust the key it is
+ saved as public server key for later use. If user does not trust the
+ key this returns FALSE. */
+
+static int silc_verify_public_key(SilcClient client,
+ SilcClientConnection conn,
+ SilcSocketType conn_type,
+ unsigned char *pk, uint32 pk_len,
SilcSKEPKType pk_type)
{
- return TRUE;
+ return TRUE;
}
+/* Asks passphrase from user on the input line. */
+
static unsigned char *silc_ask_passphrase(SilcClient client,
SilcClientConnection conn)
{
return NULL;
}
-static int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
- char *hostname, unsigned short port,
- SilcProtocolAuthMeth *auth_meth,
- unsigned char **auth_data,
- unsigned int *auth_data_len)
-{
- return FALSE;
-}
-
-static void silc_failure(SilcClient client, SilcClientConnection conn,
- SilcProtocol protocol, void *failure)
+/* Find authentication method and authentication data by hostname and
+ port. The hostname may be IP address as well. The found authentication
+ method and authentication data is returned to `auth_meth', `auth_data'
+ and `auth_data_len'. The function returns TRUE if authentication method
+ is found and FALSE if not. `conn' may be NULL. */
+
+static int
+silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+ char *hostname, uint16 port,
+ SilcProtocolAuthMeth *auth_meth,
+ unsigned char **auth_data,
+ uint32 *auth_data_len)
{
+ return FALSE;
}
-static int key_agreement(SilcClient client, SilcClientConnection conn,
- SilcClientEntry client_entry, char *hostname,
- int port)
-{
- return FALSE;
-}
+/* Notifies application that failure packet was received. This is called
+ if there is some protocol active in the client. The `protocol' is the
+ protocol context. The `failure' is opaque pointer to the failure
+ indication. Note, that the `failure' is protocol dependant and application
+ must explicitly cast it to correct type. Usually `failure' is 32 bit
+ failure type (see protocol specs for all protocol failure types). */
-SilcClientOperations ops = {
- silc_say,
- silc_channel_message,
- silc_private_message,
- silc_notify,
- silc_command,
- silc_command_reply,
- silc_connect,
- silc_disconnect,
- silc_get_auth_method,
- silc_verify_server_key,
- silc_ask_passphrase,
- silc_failure,
- key_agreement
-};
-
-/* Loads public and private key from files. */
-
-static void silc_client_create_key_pair(char *pkcs_name, int bits,
- char *identifier,
- SilcPublicKey *pub_key,
- SilcPrivateKey *prv_key)
+static void
+silc_failure(SilcClient client, SilcClientConnection conn,
+ SilcProtocol protocol, void *failure)
{
- SilcPKCS pkcs;
- SilcRng rng;
- unsigned char *key;
- unsigned int key_len;
-
- rng = silc_rng_alloc();
- silc_rng_init(rng);
- silc_rng_global_init(rng);
-
- silc_pkcs_alloc(pkcs_name, &pkcs);
- pkcs->pkcs->init(pkcs->context, bits, rng);
-
- /* Create public key */
- key = silc_pkcs_get_public_key(pkcs, &key_len);
- *pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
- key, key_len);
-
- memset(key, 0, sizeof(key_len));
- silc_free(key);
-
- /* Create private key */
- key = silc_pkcs_get_private_key(pkcs, &key_len);
- *prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
-
- memset(key, 0, sizeof(key_len));
- silc_free(key);
-
- silc_rng_free(rng);
- silc_pkcs_free(pkcs);
+ if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
+ SilcSKEStatus status = (SilcSKEStatus)failure;
+
+ if (status == SILC_SKE_STATUS_BAD_VERSION)
+ silc_say(client, conn,
+ "You are running incompatible client version (it may be "
+ "too old or too new)");
+ if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
+ silc_say(client, conn, "Server does not support your public key type");
+ if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
+ silc_say(client, conn,
+ "Server does not support one of your proposed KE group");
+ if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
+ silc_say(client, conn,
+ "Server does not support one of your proposed cipher");
+ if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
+ silc_say(client, conn,
+ "Server does not support one of your proposed PKCS");
+ if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
+ silc_say(client, conn,
+ "Server does not support one of your proposed hash function");
+ if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
+ silc_say(client, conn,
+ "Server does not support one of your proposed HMAC");
+ if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
+ silc_say(client, conn, "Incorrect signature");
+ }
+
+ if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
+ uint32 err = (uint32)failure;
+
+ if (err == SILC_AUTH_FAILED)
+ silc_say(client, conn, "Authentication failed");
+ }
}
-static int read_keyfiles(SilcClient client, char *public_file,
- char *private_file)
+/* Asks whether the user would like to perform the key agreement protocol.
+ This is called after we have received an key agreement packet or an
+ reply to our key agreement packet. This returns TRUE if the user wants
+ the library to perform the key agreement protocol and FALSE if it is not
+ desired (application may start it later by calling the function
+ silc_client_perform_key_agreement). */
+
+static int
+silc_key_agreement(SilcClient client, SilcClientConnection conn,
+ SilcClientEntry client_entry, char *hostname,
+ int port,
+ SilcKeyAgreementCallback *completion,
+ void **context)
{
- struct stat statbuf;
+ char host[256];
- if (stat(public_file, &statbuf) != 0 ||
- stat(private_file, &statbuf) != 0)
- return FALSE;
+ /* We will just display the info on the screen and return FALSE and user
+ will have to start the key agreement with a command. */
- if (!silc_pkcs_load_private_key(private_file, &client->private_key,
- SILC_PKCS_FILE_BIN) &&
- !silc_pkcs_load_private_key(private_file, &client->private_key,
- SILC_PKCS_FILE_PEM))
- return FALSE;
+ if (hostname) {
+ memset(host, 0, sizeof(host));
+ snprintf(host, sizeof(host) - 1, "(%s on port %d)", hostname, port);
+ }
- if (!silc_pkcs_load_public_key(public_file, &client->public_key,
- SILC_PKCS_FILE_PEM) &&
- !silc_pkcs_load_public_key(public_file, &client->public_key,
- SILC_PKCS_FILE_BIN))
- return FALSE;
+ silc_say(client, conn, "%s wants to perform key agreement %s",
+ client_entry->nickname, hostname ? host : "");
- return TRUE;
-}
-
-static char *silc_create_identifier(SilcClient client)
-{
- char hostname[256], *email, *ret;
-
- if (gethostname(hostname, sizeof(hostname)) != 0)
- hostname[0] = '\0';
+ *completion = NULL;
+ *context = NULL;
- email = g_strdup_printf("%s@%s", client->username, hostname);
- ret = silc_pkcs_encode_identifier(client->username, hostname,
- client->realname, email,
- NULL, NULL);
- g_free(email);
- return ret;
+ return FALSE;
}
-static int load_keys(SilcClient client)
-{
- char *public_file, *private_file;
- char *identifier;
-
- public_file = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(),
- SILC_CLIENT_PUBLIC_KEY_NAME);
- private_file = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(),
- SILC_CLIENT_PRIVATE_KEY_NAME);
-
- if (!read_keyfiles(client, public_file, private_file)) {
- /* couldn't read key files, recreate them */
- identifier = silc_create_identifier(client);
- silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
- SILC_CLIENT_DEF_PKCS_LEN,
- identifier,
- &client->public_key,
- &client->private_key);
- silc_free(identifier);
-
- silc_pkcs_save_public_key(public_file, client->public_key,
- SILC_PKCS_FILE_PEM);
- silc_pkcs_save_private_key(private_file, client->private_key,
- NULL, SILC_PKCS_FILE_BIN);
- }
-
- g_free(public_file);
- g_free(private_file);
- return TRUE;
-}
+/* SILC client operations */
+SilcClientOperations ops = {
+ silc_say,
+ silc_channel_message,
+ silc_private_message,
+ silc_notify,
+ silc_command,
+ silc_command_reply,
+ silc_connect,
+ silc_disconnect,
+ silc_get_auth_method,
+ silc_verify_public_key,
+ silc_ask_passphrase,
+ silc_failure,
+ silc_key_agreement,
+};
static int my_silc_scheduler(void)
{
- silc_schedule_one(0);
- return 1;
+ silc_schedule_one(0);
+ return 1;
}
static CHATNET_REC *create_chatnet(void)
{
- return g_malloc0(sizeof(CHATNET_REC));
+ return g_malloc0(sizeof(CHATNET_REC));
}
static SERVER_SETUP_REC *create_server_setup(void)
{
- return g_malloc0(sizeof(SERVER_SETUP_REC));
+ return g_malloc0(sizeof(SERVER_SETUP_REC));
}
static CHANNEL_SETUP_REC *create_channel_setup(void)
{
- return g_malloc0(sizeof(CHANNEL_SETUP_REC));
+ return g_malloc0(sizeof(CHANNEL_SETUP_REC));
}
static SERVER_CONNECT_REC *create_server_connect(void)
{
- return g_malloc0(sizeof(SILC_SERVER_CONNECT_REC));
+ return g_malloc0(sizeof(SILC_SERVER_CONNECT_REC));
}
-/* Command line option variables */
void silc_core_init(void)
{
- CHAT_PROTOCOL_REC *rec;
-
- silc_client = silc_client_alloc(&ops, NULL);
- silc_client->username = g_strdup(settings_get_str("user_name"));
- silc_client->hostname = silc_net_localhost();
- silc_client->realname = g_strdup(settings_get_str("real_name"));
-
- if (!load_keys(silc_client)) {
- idletag = -1;
- return;
- }
-
- silc_client_init(silc_client);
-
- rec = g_new0(CHAT_PROTOCOL_REC, 1);
- rec->name = "SILC";
- rec->fullname = "Secure Internet Live Conferencing";
- rec->chatnet = "silcnet";
-
- rec->create_chatnet = create_chatnet;
- rec->create_server_setup = create_server_setup;
- rec->create_channel_setup = create_channel_setup;
- rec->create_server_connect = create_server_connect;
-
- rec->server_connect = (SERVER_REC *(*) (SERVER_CONNECT_REC *))
- silc_server_connect;
- rec->channel_create =
- (CHANNEL_REC *(*) (SERVER_REC *, const char *, int))
- silc_channel_create;
- rec->query_create =
- (QUERY_REC *(*) (const char *, const char *, int))
- silc_query_create;
-
- chat_protocol_register(rec);
- g_free(rec);
-
- silc_server_init();
- silc_channels_init();
- silc_queries_init();
-
- idletag = g_timeout_add(100, (GSourceFunc) my_silc_scheduler, NULL);
+ CHAT_PROTOCOL_REC *rec;
+
+ static struct poptOption options[] = {
+ { "create-key-pair", 'C', POPT_ARG_NONE, &opt_create_keypair, 0,
+ "Create new public key pair", NULL },
+ { "pkcs", 0, POPT_ARG_STRING, &opt_pkcs, 0,
+ "Set the PKCS of the public key pair", "PKCS" },
+ { "bits", 0, POPT_ARG_INT, &opt_bits, 0,
+ "Set the length of the public key pair", "VALUE" },
+ { "show-key", 'S', POPT_ARG_STRING, &opt_keyfile, 0,
+ "Show the contents of the public key", "FILE" },
+ { NULL, '\0', 0, NULL }
+ };
+
+ args_register(options);
+
+ if (opt_create_keypair == TRUE) {
+ /* Create new key pair and exit */
+ silc_cipher_register_default();
+ silc_pkcs_register_default();
+ silc_hash_register_default();
+ silc_hmac_register_default();
+ silc_client_create_key_pair(opt_pkcs, opt_bits,
+ NULL, NULL, NULL, NULL, NULL);
+ silc_free(opt_pkcs);
+ exit(0);
+ }
+
+ if (opt_keyfile == TRUE) {
+ /* Dump the key */
+ silc_cipher_register_default();
+ silc_pkcs_register_default();
+ silc_hash_register_default();
+ silc_hmac_register_default();
+ silc_client_show_key(opt_keyfile);
+ silc_free(opt_keyfile);
+ exit(0);
+ }
+
+ silc_client = silc_client_alloc(&ops, NULL);
+ silc_client->username = g_strdup(settings_get_str("user_name"));
+ silc_client->hostname = silc_net_localhost();
+ silc_client->realname = g_strdup(settings_get_str("real_name"));
+
+ if (!load_keys(silc_client)) {
+ idletag = -1;
+ return;
+ }
+
+ silc_client_init(silc_client);
+
+ rec = g_new0(CHAT_PROTOCOL_REC, 1);
+ rec->name = "SILC";
+ rec->fullname = "Secure Internet Live Conferencing";
+ rec->chatnet = "silcnet";
+ rec->create_chatnet = create_chatnet;
+ rec->create_server_setup = create_server_setup;
+ rec->create_channel_setup = create_channel_setup;
+ rec->create_server_connect = create_server_connect;
+ rec->server_connect = (SERVER_REC *(*) (SERVER_CONNECT_REC *))
+ silc_server_connect;
+ rec->channel_create = (CHANNEL_REC *(*) (SERVER_REC *, const char *, int))
+ silc_channel_create;
+ rec->query_create = (QUERY_REC *(*) (const char *, const char *, int))
+ silc_query_create;
+
+ chat_protocol_register(rec);
+ g_free(rec);
+
+ silc_server_init();
+ silc_channels_init();
+ silc_queries_init();
+
+ idletag = g_timeout_add(100, (GSourceFunc) my_silc_scheduler, NULL);
}
void silc_core_deinit(void)
{
- if (idletag != -1) {
- signal_emit("chat protocol deinit", 1,
- chat_protocol_find("SILC"));
-
- silc_server_deinit();
- silc_channels_deinit();
- silc_queries_deinit();
-
- chat_protocol_unregister("SILC");
-
- g_source_remove(idletag);
- }
-
- g_free(silc_client->username);
- g_free(silc_client->realname);
- silc_client_free(silc_client);
+ if (idletag != -1) {
+ signal_emit("chat protocol deinit", 1,
+ chat_protocol_find("SILC"));
+
+ silc_server_deinit();
+ silc_channels_deinit();
+ silc_queries_deinit();
+
+ chat_protocol_unregister("SILC");
+
+ g_source_remove(idletag);
+ }
+
+ g_free(silc_client->username);
+ g_free(silc_client->realname);
+ silc_client_free(silc_client);
}
+++ /dev/null
-/* this file is automatically generated by configure - don't change */
-void silc_core_init(void); void silc_core_deinit(void);
-void silc_init(void) { silc_core_init(); }
-void silc_deinit(void) { silc_core_deinit(); }