1/* 2 * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34/* Tiny program to help debug popper */ 35 36#include "popper.h" 37RCSID("$Id$"); 38 39static void 40loop(int s) 41{ 42 char cmd[1024]; 43 char buf[1024]; 44 fd_set fds; 45 while(1){ 46 FD_ZERO(&fds); 47 FD_SET(0, &fds); 48 FD_SET(s, &fds); 49 if(select(s+1, &fds, 0, 0, 0) < 0) 50 err(1, "select"); 51 if(FD_ISSET(0, &fds)){ 52 fgets(cmd, sizeof(cmd), stdin); 53 cmd[strlen(cmd) - 1] = '\0'; 54 strlcat (cmd, "\r\n", sizeof(cmd)); 55 write(s, cmd, strlen(cmd)); 56 } 57 if(FD_ISSET(s, &fds)){ 58 int n = read(s, buf, sizeof(buf)); 59 if(n == 0) 60 exit(0); 61 fwrite(buf, n, 1, stdout); 62 } 63 } 64} 65 66static int 67get_socket (const char *hostname, int port) 68{ 69 int ret; 70 struct addrinfo *ai, *a; 71 struct addrinfo hints; 72 char portstr[NI_MAXSERV]; 73 74 memset (&hints, 0, sizeof(hints)); 75 hints.ai_socktype = SOCK_STREAM; 76 snprintf (portstr, sizeof(portstr), "%d", ntohs(port)); 77 ret = getaddrinfo (hostname, portstr, &hints, &ai); 78 if (ret) 79 errx (1, "getaddrinfo %s: %s", hostname, gai_strerror (ret)); 80 81 for (a = ai; a != NULL; a = a->ai_next) { 82 int s; 83 84 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 85 if (s < 0) 86 continue; 87 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 88 close (s); 89 continue; 90 } 91 freeaddrinfo (ai); 92 return s; 93 } 94 err (1, "failed to connect to %s", hostname); 95} 96 97#ifdef KRB5 98static int 99doit_v5 (char *host, int port) 100{ 101 krb5_error_code ret; 102 krb5_context context; 103 krb5_auth_context auth_context = NULL; 104 krb5_principal server; 105 int s = get_socket (host, port); 106 107 ret = krb5_init_context (&context); 108 if (ret) 109 errx (1, "krb5_init_context failed: %d", ret); 110 111 ret = krb5_sname_to_principal (context, 112 host, 113 "pop", 114 KRB5_NT_SRV_HST, 115 &server); 116 if (ret) { 117 warnx ("krb5_sname_to_principal: %s", 118 krb5_get_err_text (context, ret)); 119 return 1; 120 } 121 ret = krb5_sendauth (context, 122 &auth_context, 123 &s, 124 "KPOPV1.0", 125 NULL, 126 server, 127 0, 128 NULL, 129 NULL, 130 NULL, 131 NULL, 132 NULL, 133 NULL); 134 if (ret) { 135 warnx ("krb5_sendauth: %s", 136 krb5_get_err_text (context, ret)); 137 return 1; 138 } 139 loop (s); 140 return 0; 141} 142#endif 143 144 145#ifdef KRB5 146static int use_v5 = -1; 147#endif 148static char *port_str; 149static int do_version; 150static int do_help; 151 152struct getargs args[] = { 153#ifdef KRB5 154 { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5", 155 NULL }, 156#endif 157 { "port", 'p', arg_string, &port_str, "Use this port", 158 "number-or-service" }, 159 { "version", 0, arg_flag, &do_version, "Print version", 160 NULL }, 161 { "help", 0, arg_flag, &do_help, NULL, 162 NULL } 163}; 164 165static void 166usage (int ret) 167{ 168 arg_printusage (args, 169 sizeof(args) / sizeof(args[0]), 170 NULL, 171 "hostname"); 172 exit (ret); 173} 174 175int 176main(int argc, char **argv) 177{ 178 int port = 0; 179 int ret = 1; 180 int optind = 0; 181 182 setprogname(argv[0]); 183 184 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, 185 &optind)) 186 usage (1); 187 188 argc -= optind; 189 argv += optind; 190 191 if (do_help) 192 usage (0); 193 194 if (do_version) { 195 print_version (NULL); 196 return 0; 197 } 198 199 if (argc < 1) 200 usage (1); 201 202 if (port_str) { 203 struct servent *s = roken_getservbyname (port_str, "tcp"); 204 205 if (s) 206 port = s->s_port; 207 else { 208 char *ptr; 209 210 port = strtol (port_str, &ptr, 10); 211 if (port == 0 && ptr == port_str) 212 errx (1, "Bad port `%s'", port_str); 213 port = htons(port); 214 } 215 } 216 if (port == 0) { 217#ifdef KRB5 218 port = krb5_getportbyname (NULL, "kpop", "tcp", 1109); 219#else 220#error must define KRB5 221#endif 222 } 223 224#ifdef KRB5 225 if (ret && use_v5) { 226 ret = doit_v5 (argv[0], port); 227 } 228#endif 229 return ret; 230} 231