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 main(argc, argv) 43 int argc; 44 char *argv[]; 45 { 46 krb5_data pname_data, tkt_data; 47 int sock = 0; 48 socklen_t l; 49 int retval; 50 struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */ 51 krb5_creds creds, *new_creds; 52 krb5_ccache cc; 53 krb5_data msgtext, msg; 54 krb5_context context; 55 krb5_auth_context auth_context = NULL; 56 57 #ifndef DEBUG 58 freopen("/tmp/uu-server.log", "w", stderr); 59 #endif 60 61 retval = krb5_init_context(&context); 62 if (retval) { 63 com_err(argv[0], retval, "while initializing krb5"); 64 exit(1); 65 } 66 67 #ifdef DEBUG 68 { 69 int one = 1; 70 int acc; 71 struct servent *sp; 72 socklen_t namelen = sizeof(f_inaddr); 73 74 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { 75 com_err("uu-server", errno, "creating socket"); 76 exit(3); 77 } 78 79 l_inaddr.sin_family = AF_INET; 80 l_inaddr.sin_addr.s_addr = 0; 81 if (argc == 2) { 82 l_inaddr.sin_port = htons(atoi(argv[1])); 83 } else { 84 if (!(sp = getservbyname("uu-sample", "tcp"))) { 85 com_err("uu-server", 0, "can't find uu-sample/tcp service"); 86 exit(3); 87 } 88 l_inaddr.sin_port = sp->s_port; 89 } 90 91 (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one)); 92 if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) { 93 com_err("uu-server", errno, "binding socket"); 94 exit(3); 95 } 96 if (listen(sock, 1) == -1) { 97 com_err("uu-server", errno, "listening"); 98 exit(3); 99 } 100 101 printf("Server started\n"); 102 fflush(stdout); 103 104 if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) { 105 com_err("uu-server", errno, "accepting"); 106 exit(3); 107 } 108 dup2(acc, 0); 109 close(sock); 110 sock = 0; 111 } 112 #endif 113 114 /* principal name must be sent null-terminated. */ 115 retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data); 116 if (retval || pname_data.length == 0 || 117 pname_data.data[pname_data.length - 1] != '\0') { 118 com_err ("uu-server", retval, "reading pname"); 119 return 2; 120 } 121 122 retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data); 123 if (retval) { 124 com_err ("uu-server", retval, "reading ticket data"); 125 return 2; 126 } 127 128 retval = krb5_cc_default(context, &cc); 129 if (retval) { 130 com_err("uu-server", retval, "getting credentials cache"); 131 return 4; 132 } 133 134 memset (&creds, 0, sizeof(creds)); 135 retval = krb5_cc_get_principal(context, cc, &creds.client); 136 if (retval) { 137 com_err("uu-client", retval, "getting principal name"); 138 return 6; 139 } 140 141 /* client sends it already null-terminated. */ 142 printf ("uu-server: client principal is \"%s\".\n", pname_data.data); 143 144 retval = krb5_parse_name(context, pname_data.data, &creds.server); 145 if (retval) { 146 com_err("uu-server", retval, "parsing client name"); 147 return 3; 148 } 149 150 creds.second_ticket = tkt_data; 151 printf ("uu-server: client ticket is %d bytes.\n", 152 creds.second_ticket.length); 153 154 retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc, 155 &creds, &new_creds); 156 if (retval) { 157 com_err("uu-server", retval, "getting user-user ticket"); 158 return 5; 159 } 160 161 #ifndef DEBUG 162 l = sizeof(f_inaddr); 163 if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1) 164 { 165 com_err("uu-server", errno, "getting client address"); 166 return 6; 167 } 168 #endif 169 l = sizeof(l_inaddr); 170 if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1) 171 { 172 com_err("uu-server", errno, "getting local address"); 173 return 6; 174 } 175 176 /* send a ticket/authenticator to the other side, so it can get the key 177 we're using for the krb_safe below. */ 178 179 retval = krb5_auth_con_init(context, &auth_context); 180 if (retval) { 181 com_err("uu-server", retval, "making auth_context"); 182 return 8; 183 } 184 185 retval = krb5_auth_con_setflags(context, auth_context, 186 KRB5_AUTH_CONTEXT_DO_SEQUENCE); 187 if (retval) { 188 com_err("uu-server", retval, "initializing the auth_context flags"); 189 return 8; 190 } 191 192 retval = 193 krb5_auth_con_genaddrs(context, auth_context, sock, 194 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR | 195 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR); 196 if (retval) { 197 com_err("uu-server", retval, "generating addrs for auth_context"); 198 return 9; 199 } 200 201 #if 1 202 retval = krb5_mk_req_extended(context, &auth_context, 203 AP_OPTS_USE_SESSION_KEY, 204 NULL, new_creds, &msg); 205 if (retval) { 206 com_err("uu-server", retval, "making AP_REQ"); 207 return 8; 208 } 209 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); 210 #else 211 retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock, "???", 212 0, 0, 213 AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY, 214 NULL, &creds, cc, NULL, NULL, NULL); 215 #endif 216 if (retval) 217 goto cl_short_wrt; 218 219 free(msg.data); 220 221 msgtext.length = 32; 222 msgtext.data = "Hello, other end of connection."; 223 224 retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL); 225 if (retval) { 226 com_err("uu-server", retval, "encoding message to client"); 227 return 6; 228 } 229 230 retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); 231 if (retval) { 232 cl_short_wrt: 233 com_err("uu-server", retval, "writing message to client"); 234 return 7; 235 } 236 237 238 krb5_free_data_contents(context, &msg); 239 krb5_free_data_contents(context, &pname_data); 240 /* tkt_data freed with creds */ 241 krb5_free_cred_contents(context, &creds); 242 krb5_free_creds(context, new_creds); 243 krb5_cc_close(context, cc); 244 krb5_auth_con_free(context, auth_context); 245 krb5_free_context(context); 246 return 0; 247 } 248