END_TEST START_TEST (test_saslplugin_request_cram_md5) { g_print("Starting test_saslplugin_request_cram_md5\n"); gpointer plugin; Gsasl *gsasl_context; Gsasl_session *gsasl_session; plugin = g_object_new(GSIGNOND_TYPE_SASL_PLUGIN, NULL); fail_if(plugin == NULL); fail_if (gsasl_init (&gsasl_context) != GSASL_OK); fail_if (gsasl_server_start (gsasl_context, "CRAM-MD5", &gsasl_session) != GSASL_OK); GSignondSessionData* result = NULL; GSignondSessionData* result_final = NULL; GError* error = NULL; g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result_final); g_signal_connect(plugin, "response", G_CALLBACK(response_callback), &result); g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error); GSignondSessionData* data = gsignond_dictionary_new(); char* server_challenge; fail_if(gsasl_step64(gsasl_session, "", &server_challenge) != GSASL_NEEDS_MORE); gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge); free(server_challenge); gsignond_session_data_set_username(data, "*****@*****.**"); gsignond_session_data_set_secret(data, "megapassword"); gsignond_plugin_request_initial(plugin, data, NULL, "CRAM-MD5"); fail_if(result != NULL); fail_if(result_final == NULL); fail_if(error != NULL); const gchar* response = gsignond_dictionary_get_string(result_final, "ResponseBase64"); char *response_decoded; size_t response_decoded_len; fail_if(gsasl_base64_from(response, strlen(response), &response_decoded, &response_decoded_len) != GSASL_OK); fail_if(strncmp(response_decoded, "*****@*****.**", strlen("*****@*****.**")) != 0); free(response_decoded); gsignond_dictionary_unref(result_final); result_final = NULL; gsasl_finish(gsasl_session); gsasl_done(gsasl_context); gsignond_dictionary_unref(data); g_object_unref(plugin); }
SASLSession::~SASLSession() { gsasl_finish(m_gsaslSession); m_gsaslSession = 0; gsasl_done(m_gsaslContext); m_gsaslContext = 0; }
static char * sasl_auth_plain( char *user, char *pass) { Gsasl *ctx = NULL; Gsasl_session *session; char *p = NULL; const char *mech = "PLAIN"; if (gsasl_init(&ctx) != GSASL_OK) /* TODO: do this only once at startup */ return p; if (gsasl_client_start(ctx, mech, &session) != GSASL_OK) { gsasl_done(ctx); return p; } gsasl_property_set(session, GSASL_AUTHID, user); gsasl_property_set(session, GSASL_PASSWORD, pass); if (gsasl_step64(session, NULL, &p) != GSASL_OK) FreeAndNull(p); gsasl_finish(session); gsasl_done(ctx); return p; }
int main(int argc, char *argv[]) { Gsasl *ctx; (void)argc; (void)argv; if (gsasl_init(&ctx) == GSASL_OK) { (void)gsasl_client_support_p(ctx, "CRAM-MD5"); gsasl_done(ctx); return 0; } return 0; }
int main (int argc, char *argv[]) { Gsasl *ctx = NULL; int rc; /* Initialize library. */ if ((rc = gsasl_init (&ctx)) != GSASL_OK) { printf ("Cannot initialize libgsasl (%d): %s", rc, gsasl_strerror (rc)); return 1; } /* Do it. */ client (ctx); /* Cleanup. */ gsasl_done (ctx); return 0; }
/** * gsasl_init: * @ctx: pointer to libgsasl handle. * * This functions initializes libgsasl. The handle pointed to by ctx * is valid for use with other libgsasl functions iff this function is * successful. It also register all builtin SASL mechanisms, using * gsasl_register(). * * Return value: GSASL_OK iff successful, otherwise GSASL_MALLOC_ERROR. **/ int gsasl_init (Gsasl ** ctx) { size_t i; int rc; if (gc_init () != GC_OK) return GSASL_CRYPTO_ERROR; *ctx = (Gsasl *) calloc (1, sizeof (**ctx)); if (*ctx == NULL) return GSASL_MALLOC_ERROR; rc = register_builtin_mechs (*ctx); if (rc != GSASL_OK) { gsasl_done (*ctx); return rc; } return GSASL_OK; }
void doit (void) { Gsasl_ctx *ctx = NULL; Gsasl_session_ctx *server = NULL, *client = NULL; char *s1 = NULL, *s2 = NULL; int rc, res1, res2; rc = gsasl_init (&ctx); if (rc != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } gsasl_client_callback_service_set (ctx, client_cb_service); gsasl_client_callback_authentication_id_set (ctx, client_cb_authentication_id); gsasl_server_callback_gssapi_set (ctx, server_cb_gssapi); for (i = 0; i < 5; i++) { rc = gsasl_server_start (ctx, "GSSAPI", &server); if (rc != GSASL_OK) { fail ("gsasl_server_start() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } rc = gsasl_client_start (ctx, "GSSAPI", &client); if (rc != GSASL_OK) { fail ("gsasl_client_start() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } do { res1 = gsasl_step64 (server, s1, &s2); if (s1) { free (s1); s1 = NULL; } if (res1 != GSASL_OK && res1 != GSASL_NEEDS_MORE) { fail ("gsasl_step64 (1) failed (%d):\n%s\n", res1, gsasl_strerror (res1)); return; } if (debug) printf ("S: %s\n", s2); if (res1 == GSASL_OK && strcmp (s2, "") == 0) break; res2 = gsasl_step64 (client, s2, &s1); free (s2); if (res2 != GSASL_OK && res2 != GSASL_NEEDS_MORE) { fail ("gsasl_step64 (2) failed (%d):\n%s\n", res2, gsasl_strerror (res2)); return; } if (debug) printf ("C: %s\n", s1); } while (res1 != GSASL_OK || res2 != GSASL_OK); if (s1) { free (s1); s1 = NULL; } if (debug) printf ("\n"); gsasl_client_finish (client); gsasl_server_finish (server); } gsasl_done (ctx); }
void doit (void) { Gsasl *ctx = NULL; const char *str; const char *p; int res; res = gsasl_init (&ctx); if (res != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res)); return; } str = "FOO BAR FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p ? p : "(null)"); if (p) fail ("FAIL: not null?!\n"); if (gsasl_client_support_p (ctx, "EXTERNAL")) { str = "FOO BAR EXTERNAL BAR FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p); if (!p || strcmp (p, "EXTERNAL") != 0) fail ("FAIL: not external?!\n"); } if (gsasl_client_support_p (ctx, "CRAM-MD5")) { str = "FOO BAR CRAM-MD5 BAR FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p); if (!p || strcmp (p, "CRAM-MD5") != 0) fail ("FAIL: not cram-md5?!\n"); } if (gsasl_client_support_p (ctx, "PLAIN") && gsasl_client_support_p (ctx, "CRAM-MD5")) { str = "FOO PLAIN CRAM-MD5 BAR FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p); if (!p || strcmp (p, "CRAM-MD5") != 0) fail ("FAIL: not cram-md5?!\n"); } if (gsasl_client_support_p (ctx, "PLAIN")) { str = "FOO PLAIN BAR FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p); if (!p || strcmp (p, "PLAIN") != 0) fail ("FAIL: not plain?!\n"); } if (gsasl_client_support_p (ctx, "PLAIN") && gsasl_client_support_p (ctx, "CRAM-MD5") && gsasl_client_support_p (ctx, "DIGEST-MD5")) { str = "FOO PLAIN CRAM-MD5 DIGEST-MD5 FOO"; p = gsasl_client_suggest_mechanism (ctx, str); if (debug) printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p); if (!p || strcmp (p, "CRAM-MD5") != 0) fail ("FAIL: not cram-md5?!\n"); } gsasl_done (ctx); }
void doit (void) { Gsasl *ctx = NULL; Gsasl_session *server = NULL, *client = NULL; char *s1 = NULL, *s2 = NULL; int rc, res1, res2; if (getenv ("GNUGSS") && strcmp (getenv ("GNUGSS"), "no") == 0) { fail ("Not using GNU GSS, skipping self-test.\n"); exit (77); } rc = gsasl_init (&ctx); if (rc != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } if (!gsasl_client_support_p (ctx, "GS2-KRB5") || !gsasl_server_support_p (ctx, "GS2-KRB5")) { gsasl_done (ctx); fail ("No support for GS2-KRB5.\n"); exit (77); } gsasl_callback_set (ctx, callback); for (i = 0; i < 5; i++) { bool client_first = (i % 2) == 0; rc = gsasl_server_start (ctx, "GS2-KRB5", &server); if (rc != GSASL_OK) { fail ("gsasl_server_start() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } rc = gsasl_client_start (ctx, "GS2-KRB5", &client); if (rc != GSASL_OK) { fail ("gsasl_client_start() failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } if (client_first) { rc = gsasl_step64 (client, NULL, &s1); if (rc != GSASL_OK && rc != GSASL_NEEDS_MORE) { fail ("gsasl_step64 failed (%d):\n%s\n", rc, gsasl_strerror (rc)); return; } if (debug) printf ("C: %s [%c]\n", s1, ret_char (rc)); } do { res1 = gsasl_step64 (server, s1, &s2); if (s1 == NULL && res1 == GSASL_OK) fail ("gsasl_step64 direct success?\n"); if (s1) { gsasl_free (s1); s1 = NULL; } if (res1 != GSASL_OK && res1 != GSASL_NEEDS_MORE) { fail ("gsasl_step64 (1) failed (%d):\n%s\n", res1, gsasl_strerror (res1)); return; } if (debug) printf ("S: %s [%c]\n", s2, ret_char (res1)); res2 = gsasl_step64 (client, s2, &s1); gsasl_free (s2); if (res2 != GSASL_OK && res2 != GSASL_NEEDS_MORE) { fail ("gsasl_step64 (2) failed (%d):\n%s\n", res2, gsasl_strerror (res2)); return; } if (debug) printf ("C: %s [%c]\n", s1, ret_char (res2)); } while (res1 != GSASL_OK || res2 != GSASL_OK); if (s1) { gsasl_free (s1); s1 = NULL; } if (debug) printf ("\n"); gsasl_finish (client); gsasl_finish (server); } gsasl_done (ctx); }
static void sasl_authenticate( SV *client, mongo_link *link ) { Gsasl *ctx = NULL; Gsasl_session *session; SV *username, *mechanism, *conv_id; HV *result; /* response document from mongod */ char *p, *buf; /* I/O buffers for gsasl */ int rc; char out_buf[8192]; mechanism = perl_mongo_call_method( client, "sasl_mechanism", 0, 0 ); if ( !SvOK( mechanism ) ) { croak( "MongoDB: Could not retrieve SASL mechanism from client object\n" ); } if ( strncmp( "PLAIN", SvPV_nolen( mechanism ), 5 ) == 0 ) { /* SASL PLAIN does not require a libgsasl conversation loop, so we can handle it elsewhere */ return perl_mongo_call_method( client, "_sasl_plain_authenticate", 0, 0 ); } if ( ( rc = gsasl_init( &ctx ) ) != GSASL_OK ) { croak( "MongoDB: Cannot initialize libgsasl (%d): %s\n", rc, gsasl_strerror(rc) ); } if ( ( rc = gsasl_client_start( ctx, SvPV_nolen( mechanism ), &session ) ) != GSASL_OK ) { croak( "MongoDB: Cannot initialize SASL client (%d): %s\n", rc, gsasl_strerror(rc) ); } username = perl_mongo_call_method( client, "username", 0, 0 ); if ( !SvOK( username ) ) { croak( "MongoDB: Cannot start SASL session without username. Specify username in constructor\n" ); } gsasl_property_set( session, GSASL_SERVICE, "mongodb" ); gsasl_property_set( session, GSASL_HOSTNAME, link->master->host ); gsasl_property_set( session, GSASL_AUTHID, SvPV_nolen( username ) ); rc = gsasl_step64( session, "", &p ); if ( ( rc != GSASL_OK ) && ( rc != GSASL_NEEDS_MORE ) ) { croak( "MongoDB: No data from GSSAPI. Did you run kinit?\n" ); } if ( ! strncpy( out_buf, p, 8192 ) ) { croak( "MongoDB: Unable to copy SASL output buffer\n" ); } gsasl_free( p ); result = (HV *)SvRV( perl_mongo_call_method( client, "_sasl_start", 0, 2, newSVpv( out_buf, 0 ), mechanism ) ); #if 0 fprintf( stderr, "result conv id = [%s]\n", SvPV_nolen( *hv_fetch( result, "conversationId", 14, FALSE ) ) ); fprintf( stderr, "result payload = [%s]\n", SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) ) ); #endif buf = SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) ); conv_id = *hv_fetch( result, "conversationId", 14, FALSE ); do { rc = gsasl_step64( session, buf, &p ); if ( ( rc != GSASL_OK ) && ( rc != GSASL_NEEDS_MORE ) ) { croak( "MongoDB: SASL step error (%d): %s\n", rc, gsasl_strerror(rc) ); } if ( ! strncpy( out_buf, p, 8192 ) ) { croak( "MongoDB: Unable to copy SASL output buffer\n" ); } gsasl_free( p ); result = (HV *)SvRV( perl_mongo_call_method( client, "_sasl_continue", 0, 2, newSVpv( out_buf, 0 ), conv_id ) ); #if 0 fprintf( stderr, "result conv id = [%s]\n", SvPV_nolen( *hv_fetch( result, "conversationId", 14, FALSE ) ) ); fprintf( stderr, "result payload = [%s]\n", SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) ) ); #endif buf = SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) ); } while( rc == GSASL_NEEDS_MORE ); if ( rc != GSASL_OK ) { croak( "MongoDB: SASL Authentication error (%d): %s\n", rc, gsasl_strerror(rc) ); } gsasl_finish( session ); gsasl_done( ctx ); }
int main (int argc, char *argv[]) { const char *service = argc > 1 ? argv[1] : "2000"; volatile int run = 1; struct addrinfo hints, *addrs; int sockfd; int rc; int yes = 1; Gsasl *ctx; struct cfg cfg; setvbuf (stdout, NULL, _IONBF, 0); if (argc != 7) { printf ("Usage: %s PORT CFG-PATH STATE-PATH SP-METADATA " "SP-KEY SP-CERT\n", argv[0]); exit (EXIT_FAILURE); } cfg.cfg_path = argv[2]; cfg.state_path = argv[3]; cfg.sp_metadata = argv[4]; cfg.sp_key = argv[5]; cfg.sp_cert = argv[6]; rc = gsasl_init (&ctx); if (rc < 0) { printf ("gsasl_init (%d): %s\n", rc, gsasl_strerror (rc)); exit (EXIT_FAILURE); } printf ("%s [gsasl header %s library %s]\n", argv[0], GSASL_VERSION, gsasl_check_version (NULL)); gsasl_callback_set (ctx, callback); gsasl_callback_hook_set (ctx, &cfg); memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo (NULL, service, &hints, &addrs); if (rc < 0) { printf ("getaddrinfo: %s\n", gai_strerror (rc)); exit (EXIT_FAILURE); } sockfd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol); if (sockfd < 0) { perror ("socket"); exit (EXIT_FAILURE); } if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) < 0) { perror ("setsockopt"); exit (EXIT_FAILURE); } rc = bind (sockfd, addrs->ai_addr, addrs->ai_addrlen); if (rc < 0) { perror ("bind"); exit (EXIT_FAILURE); } freeaddrinfo (addrs); rc = listen (sockfd, SOMAXCONN); if (rc < 0) { perror ("listen"); exit (EXIT_FAILURE); } signal (SIGPIPE, SIG_IGN); while (run) { struct sockaddr from; socklen_t fromlen = sizeof (from); char host[NI_MAXHOST]; int fd; FILE *fh; fd = accept (sockfd, &from, &fromlen); if (fd < 0) { perror ("accept"); continue; } rc = getnameinfo (&from, fromlen, host, sizeof (host), NULL, 0, NI_NUMERICHOST); if (rc == 0) printf ("connection from %s\n", host); else printf ("getnameinfo: %s\n", gai_strerror (rc)); fh = fdopen (fd, "w+"); if (!fh) { perror ("fdopen"); close (fd); continue; } smtp (fh, ctx); fclose (fh); } close (sockfd); gsasl_done (ctx); return 0; }
END_TEST START_TEST (test_saslplugin_request_scram_sha_1) { g_print("Starting test_saslplugin_request_scram_sha_1\n"); gpointer plugin; Gsasl *gsasl_context; Gsasl_session *gsasl_session; plugin = g_object_new(GSIGNOND_TYPE_SASL_PLUGIN, NULL); fail_if(plugin == NULL); fail_if (gsasl_init (&gsasl_context) != GSASL_OK); fail_if (gsasl_server_start (gsasl_context, "SCRAM-SHA-1", &gsasl_session) != GSASL_OK); GSignondSessionData* result = NULL; GSignondSessionData* result_final = NULL; GError* error = NULL; g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result_final); g_signal_connect(plugin, "response", G_CALLBACK(response_callback), &result); g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error); GSignondSessionData* data = gsignond_dictionary_new(); char* server_challenge; fail_if(gsasl_step64(gsasl_session, "", &server_challenge) != GSASL_NEEDS_MORE); gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge); free(server_challenge); gsignond_session_data_set_username(data, "*****@*****.**"); gsignond_session_data_set_secret(data, "megapassword"); gsignond_plugin_request_initial(plugin, data, NULL, "SCRAM-SHA-1"); fail_if(result == NULL); fail_if(result_final != NULL); fail_if(error != NULL); gsasl_property_set(gsasl_session, GSASL_PASSWORD, "megapassword"); fail_if (gsasl_step64(gsasl_session, gsignond_dictionary_get_string(result, "ResponseBase64"), &server_challenge) != GSASL_NEEDS_MORE); gsignond_dictionary_unref(result); result = NULL; gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge); free(server_challenge); gsignond_plugin_request(plugin, data); fail_if(result == NULL); fail_if(result_final != NULL); fail_if(error != NULL); fail_if (gsasl_step64(gsasl_session, gsignond_dictionary_get_string(result, "ResponseBase64"), &server_challenge) != GSASL_OK); gsignond_dictionary_unref(result); result = NULL; gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge); free(server_challenge); gsignond_plugin_request(plugin, data); fail_if(result != NULL); fail_if(result_final == NULL); fail_if(error != NULL); fail_if(strlen(gsignond_dictionary_get_string(result_final, "ResponseBase64")) > 0); gsignond_dictionary_unref(result_final); result_final = NULL; gsasl_finish(gsasl_session); gsasl_done(gsasl_context); gsignond_dictionary_unref(data); g_object_unref(plugin); }
void doit (void) { Gsasl_ctx *ctx = NULL; Gsasl_session_ctx *xctx = NULL; char output[MAX_LINE_LENGTH]; size_t outputlen; int i, j; int res; if (!gsasl_check_version (GSASL_VERSION)) fail ("gsasl_check_version failure"); success ("Header version %s library version %s\n", GSASL_VERSION, gsasl_check_version (NULL)); res = gsasl_init (&ctx); if (res != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res)); return; } gsasl_client_callback_authentication_id_set (ctx, client_callback_authentication_id); gsasl_client_callback_authorization_id_set (ctx, client_callback_authorization_id); gsasl_client_callback_password_set (ctx, client_callback_password); gsasl_server_callback_validate_set (ctx, server_callback_validate); gsasl_server_callback_retrieve_set (ctx, server_callback_retrieve); gsasl_client_callback_service_set (ctx, client_callback_service); gsasl_client_callback_anonymous_set (ctx, client_callback_anonymous); gsasl_server_callback_anonymous_set (ctx, server_callback_anonymous); gsasl_server_callback_external_set (ctx, server_callback_external); gsasl_client_callback_passcode_set (ctx, client_callback_passcode); gsasl_client_callback_pin_set (ctx, client_callback_pin); gsasl_server_callback_securid_set (ctx, server_callback_securid); outputlen = sizeof (output); res = gsasl_client_listmech (ctx, output, &outputlen); if (res != GSASL_OK) fail ("gsasl_client_listmech() failed (%d):\n%s\n", res, gsasl_strerror (res)); outputlen = sizeof (output); res = gsasl_server_listmech (ctx, output, &outputlen); if (res != GSASL_OK) fail ("gsasl_server_listmech() failed (%d):\n%s\n", res, gsasl_strerror (res)); for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++) { gsasl_application_data_set (ctx, &i); if (debug) printf ("Entry %d %s mechanism %s:\n", i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech); if (sasltv[i].clientp) res = gsasl_client_support_p (ctx, sasltv[i].mech); else res = gsasl_server_support_p (ctx, sasltv[i].mech); if (!res) continue; if (sasltv[i].clientp) res = gsasl_client_start (ctx, sasltv[i].mech, &xctx); else res = gsasl_server_start (ctx, sasltv[i].mech, &xctx); if (res != GSASL_OK) { fail ("SASL %s start for mechanism %s failed (%d):\n%s\n", sasltv[i].clientp ? "client" : "server", sasltv[i].mech, res, gsasl_strerror (res)); continue; } for (j = 0; sasltv[i].step[j]; j += 2) { if (sasltv[i].clientp) gsasl_client_application_data_set (xctx, &j); else gsasl_server_application_data_set (xctx, &j); if (debug) printf ("Input : %s\n", sasltv[i].step[j] ? sasltv[i].step[j] : ""); output[0] = '\0'; outputlen = sizeof (output); if (sasltv[i].clientp) res = gsasl_client_step_base64 (xctx, sasltv[i].step[j], output, outputlen); else res = gsasl_server_step_base64 (xctx, sasltv[i].step[j], output, outputlen); if (debug) printf ("Output: %s\n", output); if (res != GSASL_OK && res != GSASL_NEEDS_MORE) break; if (strlen (output) != strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "")) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d length error\n", i, sasltv[i].mech, j); j = -1; break; } if (strcmp (output, sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "") != 0) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d data error\n", i, sasltv[i].mech, j); j = -1; break; } if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK) break; } if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2]) fail ("SASL entry %d mechanism %s step %d code ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE) fail ("SASL entry %d mechanism %s step %d table ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res != GSASL_OK) fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n", i, sasltv[i].mech, j, res, gsasl_strerror (res)); else printf ("PASS: simple %s %s %d\n", sasltv[i].mech, sasltv[i].clientp ? "client" : "server", i); if (sasltv[i].clientp) gsasl_client_finish (xctx); else gsasl_server_finish (xctx); if (debug) printf ("\n"); } gsasl_done (ctx); }
SASLMechanismFactory::~SASLMechanismFactory() { gsasl_done(m_gsaslContext); }
int main (int argc, char *argv[]) { Gsasl *ctx = NULL; int res; char *in; char *connect_hostname = NULL; char *connect_service = NULL; #ifdef HAVE_LIBGNUTLS gnutls_anon_client_credentials anoncred; gnutls_certificate_credentials x509cred; #endif set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); /* This is necessary for modern MinGW compilers that provide working getaddrinfo function, which results in gnulib not detecting that it is broken. The proper fix is for gnulib to wrap the getaddrinfo call and initialize Windows sockets in the wrapper. */ (void) gl_sockets_startup (SOCKETS_1_1); if (cmdline_parser (argc, argv, &args_info) != 0) return EXIT_FAILURE; if (args_info.version_given) { const char *p = PACKAGE_NAME; if (strcmp (gsasl_check_version (NULL), PACKAGE_VERSION) != 0) p = PACKAGE_STRING; version_etc (stdout, "gsasl", p, gsasl_check_version (NULL), "Simon Josefsson", (char *) NULL); return EXIT_SUCCESS; } if (args_info.help_given) usage (EXIT_SUCCESS); if (!(args_info.client_flag || args_info.client_given) && !args_info.server_given && !args_info.client_mechanisms_flag && !args_info.server_mechanisms_flag) { error (0, 0, _("missing argument")); usage (EXIT_FAILURE); } if ((args_info.x509_cert_file_arg && !args_info.x509_key_file_arg) || (!args_info.x509_cert_file_arg && args_info.x509_key_file_arg)) error (EXIT_FAILURE, 0, _("need both --x509-cert-file and --x509-key-file")); if (args_info.starttls_flag && args_info.no_starttls_flag) error (EXIT_FAILURE, 0, _("cannot use both --starttls and --no-starttls")); if (args_info.smtp_flag && args_info.imap_flag) error (EXIT_FAILURE, 0, _("cannot use both --smtp and --imap")); if (!args_info.connect_given && args_info.inputs_num == 0 && !args_info.client_given && !args_info.server_given && !args_info.client_mechanisms_flag && !args_info.server_mechanisms_flag) { cmdline_parser_print_help (); emit_bug_reporting_address (); return EXIT_SUCCESS; } if (args_info.connect_given) { if (strrchr (args_info.connect_arg, ':')) { connect_hostname = xstrdup (args_info.connect_arg); *strrchr (connect_hostname, ':') = '\0'; connect_service = xstrdup (strrchr (args_info.connect_arg, ':') + 1); } else { connect_hostname = xstrdup (args_info.connect_arg); if (args_info.smtp_flag) connect_service = xstrdup ("smtp"); else connect_service = xstrdup ("imap"); } } else if (args_info.inputs_num > 0) { connect_hostname = args_info.inputs[0]; if (args_info.inputs_num > 1) connect_service = args_info.inputs[1]; else if (args_info.smtp_flag) connect_service = xstrdup ("smtp"); else connect_service = xstrdup ("imap"); } if (connect_service && !args_info.smtp_flag && !args_info.imap_flag) { if (strcmp (connect_service, "25") == 0 || strcmp (connect_service, "smtp") == 0) args_info.smtp_flag = 1; else args_info.imap_flag = 1; } if (args_info.imap_flag && !args_info.service_given) args_info.service_arg = xstrdup ("imap"); if (args_info.smtp_flag && !args_info.service_given) args_info.service_arg = xstrdup ("smtp"); if (args_info.imap_flag || args_info.smtp_flag) args_info.no_client_first_flag = 1; if (connect_hostname && !args_info.hostname_arg) args_info.hostname_arg = xstrdup (connect_hostname); if (!isatty (STDOUT_FILENO)) setvbuf (stdout, NULL, _IOLBF, BUFSIZ); res = gsasl_init (&ctx); if (res != GSASL_OK) error (EXIT_FAILURE, 0, _("initialization failure: %s"), gsasl_strerror (res)); gsasl_callback_set (ctx, callback); if (args_info.client_mechanisms_flag || args_info.server_mechanisms_flag) { char *mechs; if (args_info.client_mechanisms_flag) res = gsasl_client_mechlist (ctx, &mechs); else res = gsasl_server_mechlist (ctx, &mechs); if (res != GSASL_OK) error (EXIT_FAILURE, 0, _("error listing mechanisms: %s"), gsasl_strerror (res)); if (!args_info.quiet_given) { if (args_info.client_mechanisms_flag) fprintf (stderr, _("This client supports the following mechanisms:\n")); else fprintf (stderr, _("This server supports the following mechanisms:\n")); } fprintf (stdout, "%s\n", mechs); free (mechs); return EXIT_SUCCESS; } if (args_info.connect_given || args_info.inputs_num > 0) { struct addrinfo hints; struct addrinfo *ai0, *ai; memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; res = getaddrinfo (connect_hostname, connect_service, &hints, &ai0); if (res != 0) error (EXIT_FAILURE, 0, "%s: %s", connect_hostname, gai_strerror (res)); for (ai = ai0; ai; ai = ai->ai_next) { fprintf (stderr, "Trying %s...\n", quote (ai->ai_canonname ? ai->ai_canonname : connect_hostname)); sockfd = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) { error (0, errno, "socket"); continue; } if (connect (sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { int save_errno = errno; close (sockfd); sockfd = -1; error (0, save_errno, "connect"); continue; } break; } if (sockfd < 0) error (EXIT_FAILURE, errno, "socket"); freeaddrinfo (ai); } if (!greeting ()) return 1; #ifdef HAVE_LIBGNUTLS if (sockfd && !args_info.no_starttls_flag && (args_info.starttls_flag || has_starttls ())) { res = gnutls_global_init (); if (res < 0) error (EXIT_FAILURE, 0, _("GnuTLS global initialization failed: %s"), gnutls_strerror (res)); res = gnutls_init (&session, GNUTLS_CLIENT); if (res < 0) error (EXIT_FAILURE, 0, _("GnuTLS initialization failed: %s"), gnutls_strerror (res)); res = gnutls_set_default_priority (session); if (res < 0) error (EXIT_FAILURE, 0, _("setting GnuTLS defaults failed: %s"), gnutls_strerror (res)); res = gnutls_anon_allocate_client_credentials (&anoncred); if (res < 0) error (EXIT_FAILURE, 0, _("allocating anonymous GnuTLS credential: %s"), gnutls_strerror (res)); res = gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); if (res < 0) error (EXIT_FAILURE, 0, _("setting anonymous GnuTLS credential: %s"), gnutls_strerror (res)); res = gnutls_certificate_allocate_credentials (&x509cred); if (res < 0) error (EXIT_FAILURE, 0, _("allocating X.509 GnuTLS credential: %s"), gnutls_strerror (res)); if (args_info.x509_cert_file_arg && args_info.x509_key_file_arg) res = gnutls_certificate_set_x509_key_file (x509cred, args_info.x509_cert_file_arg, args_info.x509_key_file_arg, GNUTLS_X509_FMT_PEM); if (res != GNUTLS_E_SUCCESS) error (EXIT_FAILURE, 0, _("loading X.509 GnuTLS credential: %s"), gnutls_strerror (res)); if (args_info.x509_ca_file_arg) { res = gnutls_certificate_set_x509_trust_file (x509cred, args_info.x509_ca_file_arg, GNUTLS_X509_FMT_PEM); if (res < 0) error (EXIT_FAILURE, 0, _("no X.509 CAs found: %s"), gnutls_strerror (res)); if (res == 0) error (EXIT_FAILURE, 0, _("no X.509 CAs found")); } res = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509cred); if (res < 0) error (EXIT_FAILURE, 0, _("setting X.509 GnuTLS credential: %s"), gnutls_strerror (res)); if (args_info.priority_arg) { const char *err_pos; res = gnutls_priority_set_direct (session, args_info.priority_arg, &err_pos); if (res < 0) error (EXIT_FAILURE, 0, _("setting GnuTLS cipher priority (%s): %s\n"), gnutls_strerror (res), err_pos); } gnutls_transport_set_ptr (session, (gnutls_transport_ptr) (unsigned long) sockfd); if (!starttls ()) return 1; res = gnutls_handshake (session); if (res < 0) error (EXIT_FAILURE, 0, _("GnuTLS handshake failed: %s"), gnutls_strerror (res)); if (args_info.x509_ca_file_arg) { unsigned int status; res = gnutls_certificate_verify_peers2 (session, &status); if (res < 0) error (EXIT_FAILURE, 0, _("verifying peer certificate: %s"), gnutls_strerror (res)); if (status & GNUTLS_CERT_INVALID) error (EXIT_FAILURE, 0, _("server certificate is not trusted")); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) error (EXIT_FAILURE, 0, _("server certificate hasn't got a known issuer")); if (status & GNUTLS_CERT_REVOKED) error (EXIT_FAILURE, 0, _("server certificate has been revoked")); if (status != 0) error (EXIT_FAILURE, 0, _("could not verify server certificate (rc=%d)"), status); } #if HAVE_GNUTLS_SESSION_CHANNEL_BINDING if (!args_info.no_cb_flag) { gnutls_datum cb; res = gnutls_session_channel_binding (session, GNUTLS_CB_TLS_UNIQUE, &cb); if (res != GNUTLS_E_SUCCESS) error (EXIT_FAILURE, 0, _("getting channel binding failed: %s"), gnutls_strerror (res)); res = gsasl_base64_to ((char *) cb.data, cb.size, &b64cbtlsunique, NULL); if (res != GSASL_OK) error (EXIT_FAILURE, 0, "%s", gsasl_strerror (res)); } #endif using_tls = true; } #endif if (args_info.client_flag || args_info.client_given || args_info.server_given) { char *out; char *b64output; size_t output_len; size_t b64output_len; const char *mech; Gsasl_session *xctx = NULL; if (!select_mechanism (&in)) return 1; mech = gsasl_client_suggest_mechanism (ctx, in); if (mech == NULL) { fprintf (stderr, _("Cannot find mechanism...\n")); return 0; } if (args_info.mechanism_arg) mech = args_info.mechanism_arg; if (!authenticate (mech)) return 1; /* Authenticate using mechanism */ if (args_info.server_flag) res = gsasl_server_start (ctx, mech, &xctx); else res = gsasl_client_start (ctx, mech, &xctx); if (res != GSASL_OK) error (EXIT_FAILURE, 0, _("mechanism unavailable: %s"), gsasl_strerror (res)); in = NULL; out = NULL; if (!args_info.server_flag && args_info.no_client_first_flag) { res = GSASL_NEEDS_MORE; goto no_client_first; } do { int res2; res = gsasl_step64 (xctx, in, &out); if (res != GSASL_NEEDS_MORE && res != GSASL_OK) break; if (!step_send (out)) return 1; no_client_first: if (!args_info.quiet_given && !args_info.imap_flag && !args_info.smtp_flag) { if (args_info.server_flag) fprintf (stderr, _("Enter base64 authentication data " "from client (press RET if none):\n")); else fprintf (stderr, _("Enter base64 authentication data " "from server (press RET if none):\n")); } /* Return 1 on token, 2 on protocol success, 3 on protocol fail, 0 on errors. */ res2 = step_recv (&in); if (!res2) return 1; if (res2 == 3) error (EXIT_FAILURE, 0, _("server error")); if (res2 == 2) break; } while (args_info.imap_flag || args_info.smtp_flag || res == GSASL_NEEDS_MORE); if (res != GSASL_OK) error (EXIT_FAILURE, 0, _("mechanism error: %s"), gsasl_strerror (res)); if (!args_info.quiet_given) { if (args_info.server_flag) fprintf (stderr, _("Server authentication " "finished (client trusted)...\n")); else fprintf (stderr, _("Client authentication " "finished (server trusted)...\n")); fflush (stderr); } /* Transfer application payload */ if (args_info.application_data_flag) { struct pollfd pfd[2]; char *sockbuf = NULL; /* we read chunks of 1000 bytes at a time */ size_t sockpos = 0, sockalloc = 0, sockalloc1 = 1000; /* Setup pollfd structs... */ pfd[0].fd = STDIN_FILENO; pfd[0].events = POLLIN; if (sockfd) { pfd[1].fd = sockfd; pfd[1].events = POLLIN; } if (!args_info.quiet_given) { fprintf (stderr, _("Enter application data (EOF to finish):\n")); fflush (stderr); } while (1) { int rc; pfd[0].revents = 0; pfd[1].revents = 0; rc = poll (pfd, sockfd ? 2 : 1, -1); if (rc < 0 && errno == EINTR) continue; /* Always check for errors */ if (rc < 0) error (EXIT_FAILURE, errno, "poll"); /* We got data to read from stdin.. */ if ((pfd[0].revents & (POLLIN | POLLERR)) == POLLIN) { char *line = NULL; size_t n; ssize_t len; len = getline (&line, &n, stdin); if (len <= 0) break; if (args_info.imap_flag || args_info.smtp_flag) { if (len < 2 || strcmp (&line[len - 2], "\r\n") != 0) { line = xrealloc (line, len + 2); line[len - 1] = '\r'; line[len] = '\n'; line[len + 1] = '\0'; len++; } } else { len--; line[len] = '\0'; } res = gsasl_encode (xctx, line, len, &out, &output_len); if (res != GSASL_OK) break; if (sockfd) { #ifdef HAVE_LIBGNUTLS if (using_tls) len = gnutls_record_send (session, out, output_len); else #endif len = write (sockfd, out, output_len); if (len != output_len) error (EXIT_FAILURE, errno, "write"); } else if (!(strlen (line) == output_len && memcmp (line, out, output_len) == 0)) { res = gsasl_base64_to (out, output_len, &b64output, &b64output_len); if (res != GSASL_OK) break; if (!args_info.quiet_given) fprintf (stderr, _("Base64 encoded application " "data to send:\n")); fprintf (stdout, "%s\n", b64output); free (b64output); } free (line); free (out); } /* If there was an error, quit. */ else if (pfd[0].revents & (POLLERR | POLLHUP)) { error (0, 0, "poll stdin"); break; } /* We got data to read from the socket.. */ if (sockfd && (pfd[1].revents & (POLLIN | POLLERR)) == POLLIN) { ssize_t len; if (sockalloc == sockpos) sockbuf = x2realloc (sockbuf, &sockalloc1); sockalloc = sockalloc1; #ifdef HAVE_LIBGNUTLS if (using_tls) len = gnutls_record_recv (session, &sockbuf[sockpos], sockalloc - sockpos); else #endif len = recv (sockfd, &sockbuf[sockpos], sockalloc - sockpos, 0); if (len <= 0) break; sockpos += len; res = gsasl_decode (xctx, sockbuf, sockpos, &out, &output_len); if (res == GSASL_NEEDS_MORE) { #define MAX_INPUT_SIZE 0x100000 if (sockpos > MAX_INPUT_SIZE) error (EXIT_FAILURE, 0, _("SASL record too large: %zu\n"), sockpos); continue; } if (res != GSASL_OK) break; free (sockbuf); sockbuf = NULL; sockpos = 0; sockalloc = 0; sockalloc1 = 1000; printf ("%.*s", (int) output_len, out); free (out); } /* If there was an error, quit. */ else if (pfd[1].revents & (POLLERR | POLLHUP)) { error (0, 0, "poll socket"); break; } } if (res != GSASL_OK) error (EXIT_FAILURE, 0, _("encoding error: %s"), gsasl_strerror (res)); } if (!args_info.quiet_given) fprintf (stderr, _("Session finished...\n")); if (!logout ()) return 1; gsasl_finish (xctx); } if (sockfd) { #ifdef HAVE_LIBGNUTLS if (using_tls) { res = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (res < 0) error (EXIT_FAILURE, 0, _("terminating GnuTLS session failed: %s"), gnutls_strerror (res)); } #endif shutdown (sockfd, SHUT_RDWR); close (sockfd); } gsasl_done (ctx); #ifdef HAVE_LIBGNUTLS if (using_tls) { gnutls_deinit (session); gnutls_anon_free_client_credentials (anoncred); gnutls_certificate_free_credentials (x509cred); gnutls_global_deinit (); } #endif return 0; }
void doit (void) { Gsasl *ctx = NULL; Gsasl_session *sctx = NULL; char *out = NULL; int i, j; int res; if (!gsasl_check_version (GSASL_VERSION)) fail ("gsasl_check_version failure"); success ("Header version %s library version %s\n", GSASL_VERSION, gsasl_check_version (NULL)); res = gsasl_init (&ctx); if (res != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res)); return; } gsasl_callback_set (ctx, cb); res = gsasl_client_mechlist (ctx, &out); if (res != GSASL_OK) fail ("gsasl_client_mechlist() failed (%d):\n%s\n", res, gsasl_strerror (res)); success ("client_mechlist: %s\n", out); gsasl_free (out); out = NULL; res = gsasl_server_mechlist (ctx, &out); if (res != GSASL_OK) fail ("gsasl_server_mechlist() failed (%d):\n%s\n", res, gsasl_strerror (res)); success ("server_mechlist: %s\n", out); gsasl_free (out); out = NULL; for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++) { gsasl_callback_hook_set (ctx, &i); if (debug) printf ("Entry %d %s mechanism %s:\n", i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech); if (sasltv[i].clientp) res = gsasl_client_support_p (ctx, sasltv[i].mech); else res = gsasl_server_support_p (ctx, sasltv[i].mech); if (!res) continue; if (sasltv[i].clientp) res = gsasl_client_start (ctx, sasltv[i].mech, &sctx); else res = gsasl_server_start (ctx, sasltv[i].mech, &sctx); if (res != GSASL_OK) { fail ("SASL %s start for mechanism %s failed (%d):\n%s\n", sasltv[i].clientp ? "client" : "server", sasltv[i].mech, res, gsasl_strerror (res)); continue; } for (j = 0; sasltv[i].step[j]; j += 2) { gsasl_session_hook_set (sctx, &j); if (debug) printf ("Input : %s\n", sasltv[i].step[j] ? sasltv[i].step[j] : ""); res = gsasl_step64 (sctx, sasltv[i].step[j], &out); if (debug) printf ("Output: %s\n", out ? out : "(null)"); if (res != GSASL_OK && res != GSASL_NEEDS_MORE) { fail ("gsasl_step64 failed (%d): %s", res, gsasl_strerror (res)); break; } if (strlen (out) != strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "")) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d length error\n", i, sasltv[i].mech, j); j = -1; break; } if (strcmp (out, sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "") != 0) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d data error\n", i, sasltv[i].mech, j); j = -1; break; } gsasl_free (out); out = NULL; if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK) break; } if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2]) fail ("SASL entry %d mechanism %s step %d code ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE) fail ("SASL entry %d mechanism %s step %d table ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res != GSASL_OK) fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n", i, sasltv[i].mech, j, res, gsasl_strerror (res)); else printf ("PASS: simple %s %s %d\n", sasltv[i].mech, sasltv[i].clientp ? "client" : "server", i); { size_t outlen; res = gsasl_encode (sctx, "foo", 3, &out, &outlen); if (res != GSASL_OK) fail ("gsasl_encode %d: %s\n", res, gsasl_strerror (res)); if (outlen != 3 && memcmp (out, "foo", outlen) != 0) fail ("gsasl_encode memcmp: %.*s\n", (int) outlen, out); gsasl_free (out); out = NULL; res = gsasl_decode (sctx, "foo", 3, &out, &outlen); if (res != GSASL_OK) fail ("gsasl_decode %d: %s\n", res, gsasl_strerror (res)); if (outlen != 3 && memcmp (out, "foo", outlen) != 0) fail ("gsasl_decode memcmp: %.*s\n", (int) outlen, out); gsasl_free (out); out = NULL; } gsasl_finish (sctx); if (debug) printf ("\n"); } gsasl_done (ctx); /* Sanity check interfaces. */ gsasl_finish (NULL); gsasl_done (NULL); }