Author: metze Date: 2006-07-26 06:18:13 +0000 (Wed, 26 Jul 2006) New Revision: 17251
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17251 Log: - split out the starttls into its own function - give an operations error when tls is already on the socket metze Modified: branches/SAMBA_4_0/source/ldap_server/ldap_extended.c Changeset: Modified: branches/SAMBA_4_0/source/ldap_server/ldap_extended.c =================================================================== --- branches/SAMBA_4_0/source/ldap_server/ldap_extended.c 2006-07-26 05:19:36 UTC (rev 17250) +++ branches/SAMBA_4_0/source/ldap_server/ldap_extended.c 2006-07-26 06:18:13 UTC (rev 17251) @@ -41,56 +41,110 @@ packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket); } -NTSTATUS ldapsrv_ExtendedRequest(struct ldapsrv_call *call) +static NTSTATUS ldapsrv_StartTLS(struct ldapsrv_call *call, + struct ldapsrv_reply *reply, + const char **errstr) { - struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest; - struct ldapsrv_reply *reply; + struct ldapsrv_starttls_context *ctx; - DEBUG(10, ("Extended\n")); + (*errstr) = NULL; - reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse); - if (!reply) { - return NT_STATUS_NO_MEMORY; + /* + * TODO: give LDAP_OPERATIONS_ERROR also when + * there're pending requests or there's + * a SASL bind in progress + * (see rfc4513 section 3.1.1) + */ + if (call->conn->sockets.tls) { + (*errstr) = talloc_asprintf(reply, "START-TLS: TLS is already enabled on this LDAP session"); + return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); } - ZERO_STRUCT(reply->msg->r); + ctx = talloc(call, struct ldapsrv_starttls_context); + NT_STATUS_HAVE_NO_MEMORY(ctx); - /* check if we have a START_TLS call */ - if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) { - struct ldapsrv_starttls_context *ctx; - int result = 0; - const char *errstr; - ctx = talloc(call, struct ldapsrv_starttls_context); + ctx->conn = call->conn; + ctx->tls_socket = tls_init_server(call->conn->service->tls_params, + call->conn->connection->socket, + call->conn->connection->event.fde, + NULL); + if (!ctx->tls_socket) { + (*errstr) = talloc_asprintf(reply, "START-TLS: Failed to setup TLS socket"); + return NT_STATUS_LDAP(LDAP_OPERATIONS_ERROR); + } - if (ctx) { - ctx->conn = call->conn; - ctx->tls_socket = tls_init_server(call->conn->service->tls_params, - call->conn->connection->socket, - call->conn->connection->event.fde, - NULL); - } + call->send_callback = ldapsrv_start_tls; + call->send_private = ctx; - if (!ctx || !ctx->tls_socket) { - result = LDAP_OPERATIONS_ERROR; - errstr = talloc_asprintf(reply, - "START-TLS: Failed to setup TLS socket"); - } else { - result = LDAP_SUCCESS; - errstr = NULL; - call->send_callback = ldapsrv_start_tls; - call->send_private = ctx; - } + reply->msg->r.ExtendedResponse.response.resultcode = LDAP_SUCCESS; + reply->msg->r.ExtendedResponse.response.errormessage = NULL; - reply->msg->r.ExtendedResponse.response.resultcode = result; - reply->msg->r.ExtendedResponse.response.errormessage = errstr; - reply->msg->r.ExtendedResponse.oid = talloc_strdup(reply, req->oid); - if (!reply->msg->r.ExtendedResponse.oid) { - return NT_STATUS_NO_MEMORY; - } + ldapsrv_queue_reply(call, reply); + return NT_STATUS_OK; +} + +struct ldapsrv_extended_operation { + const char *oid; + NTSTATUS (*fn)(struct ldapsrv_call *call, struct ldapsrv_reply *reply, const char **errorstr); +}; + +static struct ldapsrv_extended_operation extended_ops[] = { + { + .oid = LDB_EXTENDED_START_TLS_OID, + .fn = ldapsrv_StartTLS, + },{ + .oid = NULL, + .fn = NULL, } +}; - /* TODO: OID not recognized, return a protocol error */ +NTSTATUS ldapsrv_ExtendedRequest(struct ldapsrv_call *call) +{ + struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest; + struct ldapsrv_reply *reply; + int result = LDAP_PROTOCOL_ERROR; + const char *error_str = NULL; + NTSTATUS status = NT_STATUS_OK; + uint32_t i; - ldapsrv_queue_reply(call, reply); - return NT_STATUS_OK; + DEBUG(10, ("Extended\n")); + + reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse); + NT_STATUS_HAVE_NO_MEMORY(reply); + + ZERO_STRUCT(reply->msg->r); + reply->msg->r.ExtendedResponse.oid = talloc_steal(reply, req->oid); + reply->msg->r.ExtendedResponse.response.resultcode = LDAP_PROTOCOL_ERROR; + reply->msg->r.ExtendedResponse.response.errormessage = NULL; + + for (i=0; extended_ops[i].oid; i++) { + if (strcmp(extended_ops[i].oid,req->oid) != 0) continue; + + /* + * if the backend function returns an error we + * need to send the reply otherwise the reply is already + * send and we need to return directly + */ + status = extended_ops[i].fn(call, reply, &error_str); + NT_STATUS_IS_OK_RETURN(status); + + if (NT_STATUS_IS_LDAP(status)) { + result = NT_STATUS_LDAP_CODE(status); + } else { + result = LDAP_OPERATIONS_ERROR; + error_str = talloc_asprintf(reply, "Extended Operation(%s) failed: %s", + req->oid, nt_errstr(status)); + } + } + /* if we haven't found the oid, then status is still NT_STATUS_OK */ + if (NT_STATUS_IS_OK(status)) { + error_str = talloc_asprintf(reply, "Extended Operation(%s) not supported", + req->oid); + } + + reply->msg->r.ExtendedResponse.response.resultcode = result; + reply->msg->r.ExtendedResponse.response.errormessage = error_str; + + ldapsrv_queue_reply(call, reply); + return NT_STATUS_OK; }
