int _gsasl_anonymous_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { *output = NULL; *output_len = 0; if (!input) return GSASL_NEEDS_MORE; /* token = 1*255TCHAR The <token> production is restricted to 255 UTF-8 encoded Unicode characters. As the encoding of a characters uses a sequence of 1 to 4 octets, a token may be long as 1020 octets. */ if (input_len == 0 || input_len > 1020) return GSASL_MECHANISM_PARSE_ERROR; /* FIXME: Validate that input is UTF-8. */ gsasl_property_set_raw (sctx, GSASL_ANONYMOUS_TOKEN, input, input_len); return gsasl_callback (NULL, sctx, GSASL_VALIDATE_ANONYMOUS); }
/** * gsasl_property_get: * @sctx: session handle. * @prop: enumerated value of Gsasl_property type, indicating the * type of data in @data. * * Retrieve the data stored in the session handle for given property * @prop, possibly invoking the application callback to get the value. * * The pointer is to live data, and must not be deallocated or * modified in any way. * * This function will invoke the application callback, using * gsasl_callback(), when a property value is not known. * * If no value is known, and no callback is specified or if the * callback fail to return data, and if any obsolete callback * functions has been set by the application, this function will try * to call these obsolete callbacks, and store the returned data as * the corresponding property. This behaviour of this function will * be removed when the obsolete callback interfaces are removed. * * Return value: Return data for property, or NULL if no value known. * * Since: 0.2.0 **/ const char * gsasl_property_get (Gsasl_session * sctx, Gsasl_property prop) { const char *p = gsasl_property_fast (sctx, prop); if (!p) { gsasl_callback (NULL, sctx, prop); p = gsasl_property_fast (sctx, prop); } #ifndef GSASL_NO_OBSOLETE if (!p) p = _gsasl_obsolete_property_map (sctx, prop); #endif return p; }
int _gsasl_securid_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { const char *authorization_id = NULL; const char *authentication_id = NULL; const char *passcode = NULL; const char *suggestedpin; char *pin = NULL; int res; size_t len; if (input_len == 0) { *output_len = 0; *output = NULL; return GSASL_NEEDS_MORE; } authorization_id = input; authentication_id = memchr (input, '\0', input_len - 1); if (authentication_id) { authentication_id++; passcode = memchr (authentication_id, '\0', input_len - strlen (authorization_id) - 1 - 1); if (passcode) { passcode++; pin = memchr (passcode, '\0', input_len - strlen (authorization_id) - 1 - strlen (authentication_id) - 1 - 1); if (pin) { pin++; if (pin && !*pin) pin = NULL; } } } if (passcode == NULL) return GSASL_MECHANISM_PARSE_ERROR; gsasl_property_set (sctx, GSASL_AUTHID, authentication_id); gsasl_property_set (sctx, GSASL_AUTHZID, authorization_id); gsasl_property_set (sctx, GSASL_PASSCODE, passcode); if (pin) gsasl_property_set (sctx, GSASL_PIN, pin); else gsasl_property_set (sctx, GSASL_PIN, NULL); res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SECURID); switch (res) { case GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE: *output = strdup (PASSCODE); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (PASSCODE); res = GSASL_NEEDS_MORE; break; case GSASL_SECURID_SERVER_NEED_NEW_PIN: suggestedpin = gsasl_property_get (sctx, GSASL_SUGGESTED_PIN); if (suggestedpin) len = strlen (suggestedpin); else len = 0; *output_len = strlen (PIN) + len; *output = malloc (*output_len); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, PIN, strlen (PIN)); if (suggestedpin) memcpy (*output + strlen (PIN), suggestedpin, len); res = GSASL_NEEDS_MORE; break; default: *output_len = 0; *output = NULL; break; } return res; }
int _gsasl_gssapi_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { _Gsasl_gssapi_server_state *state = mech_data; gss_buffer_desc bufdesc1, bufdesc2; OM_uint32 maj_stat, min_stat; gss_buffer_desc client_name; gss_OID mech_type; char tmp[4]; int res; *output = NULL; *output_len = 0; switch (state->step) { case 0: if (input_len == 0) { res = GSASL_NEEDS_MORE; break; } state->step++; /* fall through */ case 1: bufdesc1.value = (void *) input; bufdesc1.length = input_len; if (state->client) { gss_release_name (&min_stat, &state->client); state->client = GSS_C_NO_NAME; } maj_stat = gss_accept_sec_context (&min_stat, &state->context, state->cred, &bufdesc1, GSS_C_NO_CHANNEL_BINDINGS, &state->client, &mech_type, &bufdesc2, NULL, NULL, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) return GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR; *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); *output_len = bufdesc2.length; maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; if (maj_stat == GSS_S_COMPLETE) state->step++; res = GSASL_NEEDS_MORE; break; case 2: memset (tmp, 0xFF, 4); tmp[0] = GSASL_QOP_AUTH; bufdesc1.length = 4; bufdesc1.value = tmp; maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT, &bufdesc1, NULL, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_WRAP_ERROR; *output = malloc (bufdesc2.length); if (!*output) return GSASL_MALLOC_ERROR; memcpy (*output, bufdesc2.value, bufdesc2.length); *output_len = bufdesc2.length; maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; state->step++; res = GSASL_NEEDS_MORE; break; case 3: bufdesc1.value = (void *) input; bufdesc1.length = input_len; maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc1, &bufdesc2, NULL, NULL); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_UNWRAP_ERROR; /* [RFC 2222 section 7.2.1]: The client passes this token to GSS_Unwrap and interprets the first octet of resulting cleartext as a bit-mask specifying the security layers supported by the server and the second through fourth octets as the maximum size output_message to send to the server. The client then constructs data, with the first octet containing the bit-mask specifying the selected security layer, the second through fourth octets containing in network byte order the maximum size output_message the client is able to receive, and the remaining octets containing the authorization identity. The client passes the data to GSS_Wrap with conf_flag set to FALSE, and responds with the generated output_message. The client can then consider the server authenticated. */ if ((((char *) bufdesc2.value)[0] & GSASL_QOP_AUTH) == 0) { /* Integrity or privacy unsupported */ maj_stat = gss_release_buffer (&min_stat, &bufdesc2); return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR; } gsasl_property_set_raw (sctx, GSASL_AUTHZID, (char *) bufdesc2.value + 4, bufdesc2.length - 4); maj_stat = gss_display_name (&min_stat, state->client, &client_name, &mech_type); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_DISPLAY_NAME_ERROR; gsasl_property_set_raw (sctx, GSASL_GSSAPI_DISPLAY_NAME, client_name.value, client_name.length); maj_stat = gss_release_buffer (&min_stat, &bufdesc2); if (GSS_ERROR (maj_stat)) return GSASL_GSSAPI_RELEASE_BUFFER_ERROR; res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_GSSAPI); state->step++; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; }
int _gsasl_login_server_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct _Gsasl_login_server_state *state = mech_data; int res; switch (state->step) { case 0: *output = strdup (CHALLENGE_USERNAME); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (CHALLENGE_USERNAME); state->step++; res = GSASL_NEEDS_MORE; break; case 1: if (input_len == 0) return GSASL_MECHANISM_PARSE_ERROR; state->username = malloc (input_len + 1); if (state->username == NULL) return GSASL_MALLOC_ERROR; memcpy (state->username, input, input_len); state->username[input_len] = '\0'; *output = strdup (CHALLENGE_PASSWORD); if (!*output) return GSASL_MALLOC_ERROR; *output_len = strlen (CHALLENGE_PASSWORD); state->step++; res = GSASL_NEEDS_MORE; break; case 2: if (input_len == 0) return GSASL_MECHANISM_PARSE_ERROR; state->password = malloc (input_len + 1); if (state->password == NULL) return GSASL_MALLOC_ERROR; memcpy (state->password, input, input_len); state->password[input_len] = '\0'; if (input_len != strlen (state->password)) return GSASL_MECHANISM_PARSE_ERROR; gsasl_property_set (sctx, GSASL_AUTHID, state->username); gsasl_property_set (sctx, GSASL_PASSWORD, state->password); res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE); if (res == GSASL_NO_CALLBACK) { const char *key; gsasl_property_set (sctx, GSASL_AUTHZID, NULL); gsasl_property_set (sctx, GSASL_PASSWORD, NULL); key = gsasl_property_get (sctx, GSASL_PASSWORD); if (key && strlen (state->password) == strlen (key) && strcmp (state->password, key) == 0) res = GSASL_OK; else res = GSASL_AUTHENTICATION_ERROR; } *output_len = 0; *output = NULL; state->step++; break; default: res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; break; } return res; }
int _gsasl_openid20_client_step (Gsasl_session * sctx, void *mech_data, const char *input, size_t input_len, char **output, size_t * output_len) { struct openid20_client_state *state = mech_data; int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES; switch (state->step) { case 0: { const char *authzid = gsasl_property_get (sctx, GSASL_AUTHZID); const char *authid = gsasl_property_get (sctx, GSASL_AUTHID); if (!authid || !*authid) return GSASL_NO_AUTHID; res = _gsasl_gs2_generate_header (false, 'n', NULL, authzid, strlen (authid), authid, output, output_len); if (res != GSASL_OK) return res; res = GSASL_NEEDS_MORE; state->step++; } break; case 1: { gsasl_property_set_raw (sctx, GSASL_OPENID20_REDIRECT_URL, input, input_len); res = gsasl_callback (NULL, sctx, GSASL_OPENID20_AUTHENTICATE_IN_BROWSER); if (res != GSASL_OK) return res; *output_len = 1; *output = strdup ("="); if (!*output) return GSASL_MALLOC_ERROR; res = GSASL_OK; state->step++; } break; /* This step is optional. The server could have approved authentication already. Alternatively, it wanted to send some SREGs or error data and we end up here. */ case 2: { gsasl_property_set_raw (sctx, GSASL_OPENID20_OUTCOME_DATA, input, input_len); /* In the case of failures, the response MUST follow this syntax: outcome_data = "openid.error" "=" sreg_val *( "," sregp_avp ) [RFC4422] Section 3.6 explicitly prohibits additional information in an unsuccessful authentication outcome. Therefore, the openid.error and openid.error_code are to be sent as an additional challenge in the event of an unsuccessful outcome. In this case, as the protocol is lock step, the client will follow with an additional exchange containing "=", after which the server will respond with an application-level outcome. */ #define ERR_PREFIX "openid.error=" if (input_len > strlen (ERR_PREFIX) && strncmp (ERR_PREFIX, input, strlen (ERR_PREFIX)) == 0) { *output_len = 1; *output = strdup ("="); if (!*output) return GSASL_MALLOC_ERROR; res = GSASL_NEEDS_MORE; } else { *output_len = 0; *output = NULL; res = GSASL_OK; } state->step++; } break; default: break; } return res; }