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