1 /* CVS Kerberos4 client stuff. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; either version 2, or (at your option) 6 any later version. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. */ 12 13 #include <config.h> 14 15 #include "cvs.h" 16 17 #include "buffer.h" 18 #include "socket-client.h" 19 20 # include <krb.h> 21 22 extern char *krb_realmofhost (); 23 # ifndef HAVE_KRB_GET_ERR_TEXT 24 # define krb_get_err_text(status) krb_err_txt[status] 25 # endif /* HAVE_KRB_GET_ERR_TEXT */ 26 27 /* Information we need if we are going to use Kerberos encryption. */ 28 static C_Block kblock; 29 static Key_schedule sched; 30 31 32 /* This function has not been changed to deal with NO_SOCKET_TO_FD 33 (i.e., systems on which sockets cannot be converted to file 34 descriptors). The first person to try building a kerberos client 35 on such a system (OS/2, Windows 95, and maybe others) will have to 36 take care of this. */ 37 void 38 start_kerberos4_server (cvsroot_t *root, struct buffer **to_server_p, 39 struct buffer **from_server_p) 40 { 41 int s; 42 int port; 43 struct hostent *hp; 44 struct sockaddr_in sin; 45 char *hname; 46 47 s = socket (AF_INET, SOCK_STREAM, 0); 48 if (s < 0) 49 error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO)); 50 51 port = get_cvs_port_number (root); 52 53 hp = init_sockaddr (&sin, root->hostname, port); 54 55 hname = xstrdup (hp->h_name); 56 57 TRACE (TRACE_FUNCTION, "Connecting to %s(%s):%d", 58 root->hostname, 59 inet_ntoa (sin.sin_addr), 60 port); 61 62 if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0) 63 error (1, 0, "connect to %s(%s):%d failed: %s", 64 root->hostname, 65 inet_ntoa (sin.sin_addr), 66 port, SOCK_STRERROR (SOCK_ERRNO)); 67 68 { 69 const char *realm; 70 struct sockaddr_in laddr; 71 int laddrlen; 72 KTEXT_ST ticket; 73 MSG_DAT msg_data; 74 CREDENTIALS cred; 75 int status; 76 77 realm = krb_realmofhost (hname); 78 79 laddrlen = sizeof (laddr); 80 if (getsockname (s, (struct sockaddr *) &laddr, &laddrlen) < 0) 81 error (1, 0, "getsockname failed: %s", SOCK_STRERROR (SOCK_ERRNO)); 82 83 /* We don't care about the checksum, and pass it as zero. */ 84 status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd", 85 hname, realm, (unsigned long) 0, &msg_data, 86 &cred, sched, &laddr, &sin, "KCVSV1.0"); 87 if (status != KSUCCESS) 88 error (1, 0, "kerberos authentication failed: %s", 89 krb_get_err_text (status)); 90 memcpy (kblock, cred.session, sizeof (C_Block)); 91 } 92 93 close_on_exec (s); 94 95 free (hname); 96 97 /* Give caller the values it wants. */ 98 make_bufs_from_fds (s, s, 0, root, to_server_p, from_server_p, 1); 99 } 100 101 void 102 initialize_kerberos4_encryption_buffers( struct buffer **to_server_p, 103 struct buffer **from_server_p ) 104 { 105 *to_server_p = krb_encrypt_buffer_initialize (*to_server_p, 0, sched, 106 kblock, NULL); 107 *from_server_p = krb_encrypt_buffer_initialize (*from_server_p, 1, 108 sched, kblock, NULL); 109 } 110 111