Blob


1 /*
2 * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include "compat.h"
19 #include <sys/types.h>
20 #include <sys/socket.h>
22 #include <netdb.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <syslog.h>
28 #include <tls.h>
29 #include <unistd.h>
31 #if HAVE_READLINE
32 #include <readline/readline.h>
33 #include <readline/history.h>
34 #endif
36 #include "9pclib.h"
37 #include "kamid.h"
38 #include "utils.h"
39 #include "log.h"
41 /* flags */
42 int tls;
43 const char *crtpath;
44 const char *keypath;
46 /* state */
47 struct tls_config *tlsconf;
48 struct tls *ctx;
49 int sock;
51 #define PWDFID 0
53 #if HAVE_READLINE
54 static char *
55 read_line(const char *prompt)
56 {
57 char *line;
59 again:
60 if ((line = readline(prompt)) == NULL)
61 return NULL;
62 /* XXX: trim spaces? */
63 if (*line == '\0') {
64 free(line);
65 goto again;
66 }
68 add_history(line);
69 return line;
70 }
71 #else
72 static char *
73 read_line(const char *prompt)
74 {
75 char *ch, *line = NULL;
76 size_t linesize = 0;
77 ssize_t linelen;
79 linelen = getline(&line, &linesize, stdin);
80 if (linelen == -1)
81 return NULL;
83 if ((ch = strchr(line, '\n')) != NULL)
84 *ch = '\0';
85 return line;
86 }
87 #endif
89 static void ATTR_DEAD
90 usage(int ret)
91 {
92 fprintf(stderr, "usage: %s [-c] host[:port] [path]\n",
93 getprogname());
94 fprintf(stderr, PACKAGE_NAME " suite version " PACKAGE VERSION "\n");
95 exit(ret);
96 }
98 static void
99 do_version(void)
101 tversion(VERSION9P, MSIZE9P);
102 /* TODO: get reply */
105 static void
106 do_attach(const char *path)
108 if (path == NULL)
109 path = "/";
111 /* TODO: do attach */
114 static void
115 do_connect(const char *connspec, const char *path)
117 int handshake;
118 char *host, *colon;
119 const char *port;
121 host = xstrdup(connspec);
122 if ((colon = strchr(host, ':')) != NULL) {
123 *colon = '\0';
124 port = ++colon;
125 } else
126 port = "1337";
128 if (!tls)
129 fatalx("non-tls mode is not supported");
131 if ((tlsconf = tls_config_new()) == NULL)
132 fatalx("tls_config_new");
133 tls_config_insecure_noverifycert(tlsconf);
134 tls_config_insecure_noverifyname(tlsconf);
135 if (tls_config_set_keypair_file(tlsconf, crtpath, keypath) == -1)
136 fatalx("can't load certs (%s, %s)", crtpath, keypath);
138 if ((ctx = tls_client()) == NULL)
139 fatal("tls_client");
140 if (tls_configure(ctx, tlsconf) == -1)
141 fatalx("tls_configure: %s", tls_error(ctx));
143 printf("connecting to %s:%s...", host, port);
144 fflush(stdout);
146 if (tls_connect(ctx, host, port) == -1)
147 fatalx("can't connect to %s:%s: %s", host, port,
148 tls_error(ctx));
150 for (handshake = 0; !handshake;) {
151 switch (tls_handshake(ctx)) {
152 case -1:
153 fatalx("tls_handshake: %s", tls_error(ctx));
154 case 0:
155 handshake = 1;
156 break;
160 printf(" done!\n");
162 do_version();
163 do_attach(path);
165 free(host);
168 int
169 main(int argc, char **argv)
171 int ch;
173 log_init(1, LOG_DAEMON);
174 log_setverbose(1);
175 log_procinit(getprogname());
177 while ((ch = getopt(argc, argv, "C:cK:")) != -1) {
178 switch (ch) {
179 case 'C':
180 crtpath = optarg;
181 break;
182 case 'c':
183 tls = 1;
184 break;
185 case 'K':
186 keypath = optarg;
187 break;
188 default:
189 usage(1);
192 argc -= optind;
193 argv += optind;
195 if (argc == 0)
196 usage(1);
198 if ((evb = evbuffer_new()) == NULL)
199 fatal("evbuffer_new");
201 do_connect(argv[0], argv[1]);
203 for (;;) {
204 char *line;
206 if ((line = read_line("ftp> ")) == NULL)
207 break;
208 printf("read: %s\n", line);
211 printf("\n");