1 /* gsasl.c command line interface to libgsasl
2 * Copyright (C) 2002 Simon Josefsson
4 * This file is part of libgsasl.
6 * Libgsasl is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Libgsasl is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with libgsasl; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 # if !STDC_HEADERS && HAVE_MEMORY_H
50 #include "callbacks.h"
54 extern char *_gsasl_gettext (const char *str
);
55 #define _(String) _gsasl_gettext (String)
56 #define gettext_noop(String) String
57 #define N_(String) gettext_noop (String)
60 #define MAX_LINE_LENGTH BUFSIZ
63 OPTION_CLIENT_MECHANISMS
= 300,
64 OPTION_SERVER_MECHANISMS
,
69 OPTION_ENABLE_CRAM_MD5_VALIDATE
,
70 OPTION_DISABLE_CLEARTEXT_VALIDATE
73 const char *argp_program_version
= "gsasl (" PACKAGE_STRING
")";
74 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
81 char *anonymous_token
;
82 char *authentication_id
;
83 char *authorization_id
;
92 int enable_cram_md5_validate
;
93 int disable_cleartext_validate
;
97 parse_opt (int key
, char *arg
, struct argp_state
*state
)
110 authentication_id
= strdup(arg
);
114 authorization_id
= strdup(arg
);
118 password
= strdup(arg
);
122 anonymous_token
= strdup(arg
);
126 mechanism
= strdup(arg
);
131 realms
= malloc(sizeof(*realms
));
133 realms
= realloc(realms
, sizeof(*realms
)*(nrealms
+1));
135 argp_error (state
, gsasl_strerror (GSASL_MALLOC_ERROR
));
136 realms
[nrealms
++] = strdup(arg
);
140 maxbuf
= strtoul(arg
, NULL
, 0);
143 case OPTION_PASSCODE
:
144 passcode
= strdup(arg
);
148 service
= strdup(arg
);
151 case OPTION_HOSTNAME
:
152 hostname
= strdup(arg
);
155 case OPTION_SERVICENAME
:
156 servicename
= strdup(arg
);
159 case OPTION_ENABLE_CRAM_MD5_VALIDATE
:
160 enable_cram_md5_validate
= 1;
163 case OPTION_DISABLE_CLEARTEXT_VALIDATE
:
164 disable_cleartext_validate
= 1;
172 case OPTION_CLIENT_MECHANISMS
:
173 case OPTION_SERVER_MECHANISMS
:
178 argp_error (state
, "too many arguments: `%s'", arg
);
182 if (mode
== 0 && listmode
== 0)
184 argp_state_help (state
, stdout
, ARGP_HELP_STD_HELP
);
190 return ARGP_ERR_UNKNOWN
;
196 static struct argp_option options
[] = {
198 {0, 0, 0, 0, "Commands:"},
200 {"client", 'c', 0, 0, "Act as client."},
202 {"server", 's', 0, 0, "Act as server."},
204 {"client-mechanisms", OPTION_CLIENT_MECHANISMS
, 0, 0,
205 "Write name of supported client mechanisms separated by space to stdout."},
207 {"server-mechanisms", OPTION_SERVER_MECHANISMS
, 0, 0,
208 "Write name of supported server mechanisms separated by space to stdout."},
210 {0, 0, 0, 0, "SASL options (prompted for if unspecified):", 500},
212 {"anonymous-token", 'n', "STRING", 0,
213 "Token for anonymous authentication (usually mail address)."},
215 {"authentication-id", 'a', "STRING", 0,
216 "Identity of credential owner."},
218 {"authorization-id", 'z', "STRING", 0,
219 "Identity to request service for."},
221 {"password", 'p', "STRING", 0,
222 "Password for authentication."},
224 {"mechanism", 'm', "STRING", 0,
225 "Mechanism to use."},
227 {"realm", 'r', "STRING", 0,
228 "Realm (may be given more than once iff server). Defaults to hostname."},
230 {"maxbuf", 'x', "NUMBER", 0,
231 "Indicate maximum buffer size (DIGEST-MD5 only)."},
233 {"passcode", OPTION_PASSCODE
, "NUMBER", 0,
234 "Passcode for authentication (SECURID only)."},
236 {"service", OPTION_SERVICE
, "STRING", 0,
237 "Set the requested service name (should be a registered GSSAPI host "
238 "based service name)."},
240 {"hostname", OPTION_HOSTNAME
, "STRING", 0,
241 "Set the name of the server with the requested service."},
243 {"service-name", OPTION_SERVICENAME
, "STRING", 0,
244 "Set the generic server name in case of a replicated server "
245 "(DIGEST-MD5 only)."},
247 {"enable-cram-md5-validate", OPTION_ENABLE_CRAM_MD5_VALIDATE
, 0, 0,
248 "Validate CRAM-MD5 challenge and response interactively."},
250 {"disable-cleartext-validate", OPTION_DISABLE_CLEARTEXT_VALIDATE
, 0, 0,
251 "Disable cleartext validate hook, forcing server to prompt for password."},
253 {0, 0, 0, 0, "Other options:", 1000},
255 {"verbose", 'v', 0, 0, "Produce verbose output."},
257 {"quiet", 'q', 0, 0, "Don't produce any diagnostic output."},
259 {"silent", 0, 0, OPTION_ALIAS
},
264 static struct argp argp
= {
268 "GSASL -- Command line interface to libgsasl"
272 main (int argc
, char *argv
[])
274 Gsasl_ctx
*ctx
= NULL
;
277 setlocale (LC_ALL
, "");
279 argp_parse (&argp
, argc
, argv
, 0, 0, NULL
);
281 res
= gsasl_init (&ctx
);
284 fprintf(stderr
, _("GSASL error (%d): %s\n"), res
, gsasl_strerror(res
));
289 gsasl_client_callback_maxbuf_set (ctx
, client_callback_maxbuf
);
290 gsasl_client_callback_qop_set (ctx
, client_callback_qop
);
291 gsasl_client_callback_anonymous_set (ctx
, client_callback_anonymous
);
292 gsasl_client_callback_authentication_id_set (ctx
,
293 client_callback_authentication_id
);
294 gsasl_client_callback_authorization_id_set (ctx
,
295 client_callback_authorization_id
);
296 gsasl_client_callback_password_set (ctx
, client_callback_password
);
297 gsasl_client_callback_passcode_set (ctx
, client_callback_passcode
);
298 gsasl_client_callback_service_set (ctx
, client_callback_service
);
300 gsasl_server_callback_realm_set (ctx
, server_callback_realm
);
301 gsasl_server_callback_qop_set (ctx
, server_callback_qop
);
303 gsasl_server_callback_maxbuf_set (ctx
, server_callback_maxbuf
);
304 if (enable_cram_md5_validate
)
305 gsasl_server_callback_cram_md5_set (ctx
, server_callback_cram_md5
);
306 if (!disable_cleartext_validate
)
307 gsasl_server_callback_validate_set (ctx
, server_callback_validate
);
308 gsasl_server_callback_retrieve_set (ctx
, server_callback_retrieve
);
309 gsasl_server_callback_anonymous_set (ctx
, server_callback_anonymous
);
310 gsasl_server_callback_external_set (ctx
, server_callback_external
);
311 gsasl_server_callback_service_set (ctx
, server_callback_service
);
312 gsasl_server_callback_gssapi_set (ctx
, server_callback_gssapi
);
314 if (listmode
== OPTION_CLIENT_MECHANISMS
||
315 listmode
== OPTION_SERVER_MECHANISMS
)
317 char mechs
[MAX_LINE_LENGTH
];
320 mechslen
= sizeof(mechs
);
321 if (listmode
== OPTION_CLIENT_MECHANISMS
)
322 res
= gsasl_client_listmech (ctx
, mechs
, &mechslen
);
324 res
= gsasl_server_listmech (ctx
, mechs
, &mechslen
);
328 fprintf(stderr
, _("GSASL error (%d): %s\n"), res
, gsasl_strerror(res
));
333 fprintf(stderr
, _("This %s supports the following mechanisms:\n"),
334 listmode
== OPTION_CLIENT_MECHANISMS
?
335 _("client") : _("server"));
336 fprintf(stdout
, "%s\n", mechs
);
339 if (mode
== 'c' || mode
== 's')
341 char input
[MAX_LINE_LENGTH
];
342 char output
[MAX_LINE_LENGTH
];
345 Gsasl_session_ctx
*xctx
= NULL
;
352 else if (mode
== 'c')
355 fprintf(stderr
, _("Input SASL mechanism supported by server:\n"));
357 fgets(input
, MAX_LINE_LENGTH
, stdin
);
359 mech
= gsasl_client_suggest_mechanism (ctx
, input
);
362 fprintf(stderr
, _("Cannot find mechanism...\n"));
367 fprintf(stderr
, _("Libgsasl wants to use:\n"));
368 fprintf(stdout
, "%s\n", mech
);
373 fprintf(stderr
, _("Chose SASL mechanisms:\n"));
375 fgets(input
, MAX_LINE_LENGTH
, stdin
);
376 input
[strlen(input
)-1] = '\0';
379 fprintf(stderr
, _("Chosed mechanism `%s'\n"), input
);
384 res
= gsasl_client_start (ctx
, mech
, &xctx
);
386 res
= gsasl_server_start (ctx
, mech
, &xctx
);
389 fprintf(stderr
, _("Libgsasl error (%d): %s\n"),
390 res
, gsasl_strerror(res
));
396 output_len
= sizeof(output
);
400 res
= gsasl_client_step_base64 (xctx
, input
, output
, output_len
);
402 res
= gsasl_server_step_base64 (xctx
, input
, output
, output_len
);
404 if (res
!= GSASL_NEEDS_MORE
)
408 fprintf(stderr
, _("Output from %s:\n"),
409 mode
== 'c' ? _("client") : _("server"));
410 fprintf(stdout
, "%s\n", output
);
414 _("Enter base64 data from %s (press RET if none):\n"),
415 mode
== 'c' ? _("server") : _("client"));
418 fgets(input
, MAX_LINE_LENGTH
, stdin
);
420 while (res
== GSASL_NEEDS_MORE
);
424 fprintf(stderr
, _("Libgsasl error (%d): %s\n"),
425 res
, gsasl_strerror(res
));
432 fprintf(stderr
, _("Client finished (server trusted)...\n"));
434 fprintf(stderr
, _("Server finished (client trusted)...\n"));
438 gsasl_client_finish (xctx
);
440 gsasl_server_finish (xctx
);