>CLIENT:ADDRESS,{CID},{ADDR},{PRI}
+(5) Text based challenge/Response
+
+ >CLIENT:CR_RESPONSE,{CID},{KID},{response_base64}
+ >CLIENT:ENV,name1=val1
+ >CLIENT:ENV,name2=val2
+ >CLIENT:ENV,...
+ >CLIENT:ENV,END
+
+ Using the cr-response command on the client side will trigger this
+ message on the server side.
+
+ CR_RESPONSE notification. The >CR_RESPONSE fulfils the same purpose as the
+ CRV1 response in the traditional challenge/response. See that section
+ below for more details. Since this still uses the same cid as the original
+ response, we do not use the username and opaque session data in this
+ response but only contains the actual response.
+
+ It is important to note that OpenVPN2 merely passes the authentication
+ information and does not do any further checks. (E.g. if a CR was issued
+ before or if multiple CR responses were sent from the client or if
+ data has a valid base64 encoding)
+
+ This interface should be be sufficient for almost all challenge/response
+ system that can be implemented with a single round and base64 encoding the
+ response. Mechanisms that need multiple rounds or more complex answers
+ should implement a different response type than CR_RESPONSE.
+
+
Variables:
CID -- Client ID, numerical ID for each connecting client, sequence = 0,1,2,...
{
server_pushed_info(c, &buf, 4);
}
+ else if (buf_string_match_head_str(&buf, "CR_RESPONSE"))
+ {
+ receive_cr_response(c, &buf);
+ }
else
{
msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf));
#ifdef MANAGEMENT_DEF_AUTH
static void
-man_output_peer_info_env(struct management *man, struct man_def_auth_context *mdac)
+man_output_peer_info_env(struct management *man, const struct man_def_auth_context *mdac)
{
char line[256];
if (man->persist.callback.get_peer_info)
}
}
+void
+management_notify_client_cr_response(unsigned mda_key_id,
+ const struct man_def_auth_context *mdac,
+ const struct env_set *es,
+ const char *response)
+{
+ struct gc_arena gc;
+ if (management)
+ {
+ gc = gc_new();
+
+ struct buffer out = alloc_buf_gc(256, &gc);
+ msg(M_CLIENT, ">CLIENT:CR_RESPONSE,%lu,%u,%s",
+ mdac->cid, mda_key_id, response);
+ man_output_extra_env(management, "CLIENT");
+ if (management->connection.env_filter_level>0)
+ {
+ man_output_peer_info_env(management, mdac);
+ }
+ man_output_env(es, true, management->connection.env_filter_level, "CLIENT");
+ management_notify_generic(management, BSTR(&out));
+
+ gc_free(&gc);
+ }
+}
+
void
management_connection_established(struct management *management,
struct man_def_auth_context *mdac,
const struct mroute_addr *addr,
const bool primary);
+void management_notify_client_cr_response(unsigned mda_key_id,
+ const struct man_def_auth_context *mdac,
+ const struct env_set *es,
+ const char *response);
+
#endif
char *management_query_pk_sig(struct management *man, const char *b64_data,
msg(D_PUSH, "Info command was pushed by server ('%s')", m);
}
+void
+receive_cr_response(struct context *c, const struct buffer *buffer)
+{
+ struct buffer buf = *buffer;
+ const char *m = "";
+
+ if (buf_advance(&buf, 11) && buf_read_u8(&buf) == ',' && BLEN(&buf))
+ {
+ m = BSTR(&buf);
+ }
+#ifdef MANAGEMENT_DEF_AUTH
+ struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE];
+ struct man_def_auth_context *mda = session->opt->mda_context;
+ struct env_set *es = session->opt->es;
+ int key_id = session->key[KS_PRIMARY].key_id;
+
+
+ management_notify_client_cr_response(key_id, mda, es, m);
+#endif
+ msg(D_PUSH, "CR response was sent by client ('%s')", m);
+}
+
/**
* Add an option to the given push list by providing a format string.
*
void server_pushed_info(struct context *c, const struct buffer *buffer,
const int adv);
+void receive_cr_response(struct context *c, const struct buffer *buffer);
+
void incoming_push_message(struct context *c, const struct buffer *buffer);
void clone_push_list(struct options *o);