1 2 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 3 /* appl/user_user/server.c - One end of user-user client-server pair */ 4 /* 5 * Copyright 1991 by the Massachusetts Institute of Technology. 6 * All Rights Reserved. 7 * 8 * Export of this software from the United States of America may 9 * require a specific license from the United States Government. 10 * It is the responsibility of any person or organization contemplating 11 * export to obtain such a license before exporting. 12 * 13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 14 * distribute this software and its documentation for any purpose and 15 * without fee is hereby granted, provided that the above copyright 16 * notice appear in all copies and that both that copyright notice and 17 * this permission notice appear in supporting documentation, and that 18 * the name of M.I.T. not be used in advertising or publicity pertaining 19 * to distribution of the software without specific, written prior 20 * permission. Furthermore if you modify this software you must label 21 * your software as modified software and not distribute it in such a 22 * fashion that it might be confused with the original M.I.T. software. 23 * M.I.T. makes no representations about the suitability of 24 * this software for any purpose. It is provided "as is" without express 25 * or implied warranty. 26 */ 27 28 #include "k5-int.h" 29 #include "port-sockets.h" 30 #include "com_err.h" 31 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <netinet/in.h> 35 #include <arpa/inet.h> 36 #include <netdb.h> 37 #include <unistd.h> 38 #include <fcntl.h> 39 40 /* fd 0 is a tcp socket used to talk to the client */ 41 42 int 43 main(int argc, char *argv[]) 44 { 45 krb5_data pname_data, tkt_data; 46 int sock = 0; 47 socklen_t l; 48 int retval; 49 struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */ 50 krb5_creds creds, *new_creds; 51 krb5_ccache cc; 52 krb5_data msgtext, msg; 53 krb5_context context; 54 krb5_auth_context auth_context = NULL; 55 56 #ifndef DEBUG 57 freopen("/tmp/uu-server.log", "w", stderr); 58 #endif 59 60 retval = krb5_init_context(&context); 61 if (retval) { 62 com_err(argv[0], retval, "while initializing krb5"); 63 exit(1); 64 } 65 66 #ifdef DEBUG 67 { 68 int one = 1; 69 int acc; 70 struct servent *sp; 71 socklen_t namelen = sizeof(f_inaddr); 72 73 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { 74 com_err("uu-server", errno, "creating socket"); 75 exit(3); 76 } 77 78 l_inaddr.sin_family = AF_INET; 79 l_inaddr.sin_addr.s_addr = 0; 80 if (argc == 2) { 81 l_inaddr.sin_port = htons(atoi(argv[1])); 82 } else { 83 if (!(sp = getservbyname("uu-sample", "tcp"))) { 84 com_err("uu-server", 0, "can't find uu-sample/tcp service"); 85 exit(3); 86 } 87 l_inaddr.sin_port = sp->s_port; 88 } 89 90 (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one)); 91 if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) { 92 com_err("uu-server", errno, "binding socket"); 93 exit(3); 94 } 95 if (listen(sock, 1) == -1) { 96 com_err("uu-server", errno, "listening"); 97 exit(3); 98 } 99 100 printf("Server started\n"); 101 fflush(stdout); 102 103 if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) { 104 com_err("uu-server", errno, "accepting"); 105 exit(3); 106 } 107 dup2(acc, 0); 108 close(sock); 109 sock = 0; 110 } 111 #endif 112 113 /* principal name must be sent null-terminated. */ 114 retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data); 115 if (retval || pname_data.length == 0 || 116 pname_data.data[pname_data.length - 1] != '\0') { 117 com_err ("uu-server", retval, "reading pname"); 118 return 2; 119 } 120 121 retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data); 122 if (retval) { 123 com_err ("uu-server", retval, "reading ticket data"); 124 return 2; 125 } 126 127 retval = krb5_cc_default(context, &cc); 128 if (retval) { 129 com_err("uu-server", retval, "getting credentials cache"); 130 return 4; 131 } 132 133 memset (&creds, 0, sizeof(creds)); 134 retval = krb5_cc_get_principal(context, cc, &creds.client); 135 if (retval) { 136 com_err("uu-client", retval, "getting principal name"); 137 return 6; 138 } 139 140 /* client sends it already null-terminated. */ 141 printf ("uu-server: client principal is \"%s\".\n", pname_data.data); 142 143 retval = krb5_parse_name(context, pname_data.data, &creds.server); 144 if (retval) { 145 com_err("uu-server", retval, "parsing client name"); 146 return 3; 147 } 148 149 creds.second_ticket = tkt_data; 150 printf ("uu-server: client ticket is %d bytes.\n", 151 creds.second_ticket.length); 152 153 retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc, 154 &creds, &new_creds); 155 if (retval) { 156 com_err("uu-server", retval, "getting user-user ticket"); 157 return 5; 158 } 159 160 #ifndef DEBUG 161 l = sizeof(f_inaddr); 162 if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1) 163 { 164 com_err("uu-server", errno, "getting client address"); 165 return 6; 166 } 167 #endif 168 l = sizeof(l_inaddr); 169 if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1) 170 { 171 com_err("uu-server", errno, "getting local address"); 172 return 6; 173 } 174 175 /* send a ticket/authenticator to the other side, so it can get the key 176 we're using for the krb_safe below. */ 177 178 retval = krb5_auth_con_init(context, &auth_context); 179 if (retval) { 180 com_err("uu-server", retval, "making auth_context"); 181 return 8; 182 } 183 184 retval = krb5_auth_con_setflags(context, auth_context, 185 KRB5_AUTH_CONTEXT_DO_SEQUENCE); 186 if (retval) { 187 com_err("uu-server", retval, "initializing the auth_context flags"); 188 return 8; 189 } 190 191 retval = 192 krb5_auth_con_genaddrs(context, auth_context, sock, 193 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR | 194 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR); 195 if (retval) { 196 com_err("uu-server", retval, "generating addrs for auth_context"); 197 return 9; 198 } 199 200 #if 1 201 retval = krb5_mk_req_extended(context, &auth_context, 202 AP_OPTS_USE_SESSION_KEY, 203 NULL, new_creds, &msg); 204 if (retval) { 205 com_err("uu-server", retval, "making AP_REQ"); 206 return 8; 207 } 208 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); 209 #else 210 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock, "???", 211 0, 0, 212 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY, 213 NULL, &creds, cc, NULL, NULL, NULL); 214 #endif 215 if (retval) 216 goto cl_short_wrt; 217 218 free(msg.data); 219 220 msgtext.length = 32; 221 msgtext.data = "Hello, other end of connection."; 222 223 retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL); 224 if (retval) { 225 com_err("uu-server", retval, "encoding message to client"); 226 return 6; 227 } 228 229 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); 230 if (retval) { 231 cl_short_wrt: 232 com_err("uu-server", retval, "writing message to client"); 233 return 7; 234 } 235 236 237 krb5_free_data_contents(context, &msg); 238 krb5_free_data_contents(context, &pname_data); 239 /* tkt_data freed with creds */ 240 krb5_free_cred_contents(context, &creds); 241 krb5_free_creds(context, new_creds); 242 krb5_cc_close(context, cc); 243 krb5_auth_con_free(context, auth_context); 244 krb5_free_context(context); 245 return 0; 246 } 247