Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / crypto / heimdal-0.6.3 / appl / popper / pop_debug.c
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"
37 RCSID("$Id: pop_debug.c,v 1.23 2002/05/02 16:27:16 joda Exp $");
38
39 static void
40 loop(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
66 static int
67 get_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 KRB4
98 static int
99 doit_v4 (char *host, int port)
100 {
101     KTEXT_ST ticket;
102     MSG_DAT msg_data;
103     CREDENTIALS cred;
104     des_key_schedule sched;
105     int ret;
106     int s = get_socket (host, port);
107
108     ret = krb_sendauth(0,
109                        s,
110                        &ticket, 
111                        "pop",
112                        host,
113                        krb_realmofhost(host),
114                        getpid(),
115                        &msg_data,
116                        &cred,
117                        sched,
118                        NULL,
119                        NULL,
120                        "KPOPV0.1");
121     if(ret) {
122         warnx("krb_sendauth: %s", krb_get_err_text(ret));
123         return 1;
124     }
125     loop(s);
126     return 0;
127 }
128 #endif
129
130 #ifdef KRB5
131 static int
132 doit_v5 (char *host, int port)
133 {
134     krb5_error_code ret;
135     krb5_context context;
136     krb5_auth_context auth_context = NULL;
137     krb5_principal server;
138     int s = get_socket (host, port);
139
140     ret = krb5_init_context (&context);
141     if (ret)
142         errx (1, "krb5_init_context failed: %d", ret);
143     
144     ret = krb5_sname_to_principal (context,
145                                    host,
146                                    "pop",
147                                    KRB5_NT_SRV_HST,
148                                    &server);
149     if (ret) {
150         warnx ("krb5_sname_to_principal: %s",
151                krb5_get_err_text (context, ret));
152         return 1;
153     }
154     ret = krb5_sendauth (context,
155                          &auth_context,
156                          &s,
157                          "KPOPV1.0",
158                          NULL,
159                          server,
160                          0,
161                          NULL,
162                          NULL,
163                          NULL,
164                          NULL,
165                          NULL,
166                          NULL);
167      if (ret) {
168          warnx ("krb5_sendauth: %s",
169                 krb5_get_err_text (context, ret));
170          return 1;
171      }
172      loop (s);
173      return 0;
174 }
175 #endif
176
177
178 #ifdef KRB4
179 static int use_v4 = -1;
180 #endif
181 #ifdef KRB5
182 static int use_v5 = -1;
183 #endif
184 static char *port_str;
185 static int do_version;
186 static int do_help;
187
188 struct getargs args[] = {
189 #ifdef KRB4
190     { "krb4",   '4', arg_flag,          &use_v4,        "Use Kerberos V4",
191       NULL },
192 #endif
193 #ifdef KRB5
194     { "krb5",   '5', arg_flag,          &use_v5,        "Use Kerberos V5",
195       NULL },
196 #endif
197     { "port",   'p', arg_string,        &port_str,      "Use this port",
198       "number-or-service" },
199     { "version", 0,  arg_flag,          &do_version,    "Print version",
200       NULL },
201     { "help",    0,  arg_flag,          &do_help,       NULL,
202       NULL }
203 };
204
205 static void
206 usage (int ret)
207 {
208     arg_printusage (args,
209                     sizeof(args) / sizeof(args[0]),
210                     NULL,
211                     "hostname");
212     exit (ret);
213 }
214
215 int
216 main(int argc, char **argv)
217 {
218     int port = 0;
219     int ret = 1;
220     int optind = 0;
221
222     setprogname(argv[0]);
223
224     if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
225                 &optind))
226         usage (1);
227
228     argc -= optind;
229     argv += optind;
230
231     if (do_help)
232         usage (0);
233
234     if (do_version) {
235         print_version (NULL);
236         return 0;
237     }
238         
239     if (argc < 1)
240         usage (1);
241
242     if (port_str) {
243         struct servent *s = roken_getservbyname (port_str, "tcp");
244
245         if (s)
246             port = s->s_port;
247         else {
248             char *ptr;
249
250             port = strtol (port_str, &ptr, 10);
251             if (port == 0 && ptr == port_str)
252                 errx (1, "Bad port `%s'", port_str);
253             port = htons(port);
254         }
255     }
256     if (port == 0) {
257 #ifdef KRB5
258         port = krb5_getportbyname (NULL, "kpop", "tcp", 1109);
259 #elif defined(KRB4)
260         port = k_getportbyname ("kpop", "tcp", 1109);
261 #else
262 #error must define KRB4 or KRB5
263 #endif
264     }
265
266 #if defined(KRB4) && defined(KRB5)
267     if(use_v4 == -1 && use_v5 == 1)
268         use_v4 = 0;
269     if(use_v5 == -1 && use_v4 == 1)
270         use_v5 = 0;
271 #endif    
272
273 #ifdef KRB5
274     if (ret && use_v5) {
275         ret = doit_v5 (argv[0], port);
276     }
277 #endif
278 #ifdef KRB4
279     if (ret && use_v4) {
280         ret = doit_v4 (argv[0], port);
281     }
282 #endif
283     return ret;
284 }