/* Tell the client the authentication failed. This is only used during the authentication exchange (i.e. inside try_auth()). */ static svn_error_t * fail_auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, sasl_conn_t *sasl_ctx) { const char *msg = sasl_errdetail(sasl_ctx); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(c)", "failure", msg)); return svn_ra_svn_flush(conn, pool); }
svn_error_t *svn_ra_svn_write_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_hash_t *props) { apr_pool_t *iterpool; apr_hash_index_t *hi; const void *key; void *val; const char *propname; svn_string_t *propval; if (props) { iterpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) { svn_pool_clear(iterpool); apr_hash_this(hi, &key, NULL, &val); propname = key; propval = val; SVN_ERR(svn_ra_svn_write_tuple(conn, iterpool, "cs", propname, propval)); } svn_pool_destroy(iterpool); } return SVN_NO_ERROR; }
static svn_error_t *try_auth(svn_ra_svn_conn_t *conn, sasl_conn_t *sasl_ctx, apr_pool_t *pool, server_baton_t *b, svn_boolean_t *success) { const char *out, *mech; const svn_string_t *arg = NULL, *in; unsigned int outlen; int result; svn_boolean_t use_base64; *success = FALSE; /* Read the client's chosen mech and the initial token. */ SVN_ERR(svn_ra_svn_read_tuple(conn, pool, "w(?s)", &mech, &in)); if (strcmp(mech, "EXTERNAL") == 0 && !in) in = svn_string_create(b->tunnel_user, pool); else if (in) in = svn_base64_decode_string(in, pool); /* For CRAM-MD5, we don't base64-encode stuff. */ use_base64 = (strcmp(mech, "CRAM-MD5") != 0); result = sasl_server_start(sasl_ctx, mech, in ? in->data : NULL, in ? in->len : 0, &out, &outlen); if (result != SASL_OK && result != SASL_CONTINUE) return fail_auth(conn, pool, sasl_ctx); while (result == SASL_CONTINUE) { svn_ra_svn_item_t *item; arg = svn_string_ncreate(out, outlen, pool); /* Encode what we send to the client. */ if (use_base64) arg = svn_base64_encode_string2(arg, TRUE, pool); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(s)", "step", arg)); /* Read and decode the client response. */ SVN_ERR(svn_ra_svn_read_item(conn, pool, &item)); if (item->kind != SVN_RA_SVN_STRING) return SVN_NO_ERROR; in = item->u.string; if (use_base64) in = svn_base64_decode_string(in, pool); result = sasl_server_step(sasl_ctx, in->data, in->len, &out, &outlen); } if (result != SASL_OK) return fail_auth(conn, pool, sasl_ctx); /* Send our last response, if necessary. */ if (outlen) arg = svn_base64_encode_string2(svn_string_ncreate(out, outlen, pool), TRUE, pool); else arg = NULL; *success = TRUE; SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(?s)", "success", arg)); return SVN_NO_ERROR; }