110 lines
3.5 KiB
C
110 lines
3.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ldap.h>
|
|
#include "rdp_broker.h"
|
|
|
|
int authenticate_user(const char *username, const char *password,
|
|
const char *samba_server, int samba_port,
|
|
const char *base_dn) {
|
|
|
|
LOG(LOG_DEBUG, "Authenticating user: %s", username);
|
|
|
|
if (!username || !password || strlen(password) == 0) {
|
|
LOG(LOG_WARN, "Empty username or password");
|
|
return -1;
|
|
}
|
|
|
|
/* Perform LDAP bind to validate credentials */
|
|
int result = ldap_bind_check(samba_server, samba_port, username,
|
|
password, base_dn);
|
|
|
|
if (result == 0) {
|
|
LOG(LOG_INFO, "Authentication successful for user: %s", username);
|
|
return 0;
|
|
} else {
|
|
LOG(LOG_WARN, "Authentication failed for user: %s", username);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int ldap_bind_check(const char *server, int port, const char *username,
|
|
const char *password, const char *base_dn) {
|
|
LDAP *ld = NULL;
|
|
int rc;
|
|
char ldap_uri[512];
|
|
char bind_dn[512];
|
|
int version = LDAP_VERSION3;
|
|
|
|
/* Construct LDAP URI */
|
|
snprintf(ldap_uri, sizeof(ldap_uri), "ldap://%s:%d", server, port);
|
|
|
|
/* Initialize LDAP connection */
|
|
rc = ldap_initialize(&ld, ldap_uri);
|
|
if (rc != LDAP_SUCCESS) {
|
|
LOG(LOG_ERROR, "LDAP initialization failed: %s", ldap_err2string(rc));
|
|
return -1;
|
|
}
|
|
|
|
/* Set LDAP version */
|
|
rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
|
|
if (rc != LDAP_OPT_SUCCESS) {
|
|
LOG(LOG_ERROR, "Failed to set LDAP version: %s", ldap_err2string(rc));
|
|
ldap_unbind_ext_s(ld, NULL, NULL);
|
|
return -1;
|
|
}
|
|
|
|
/* Construct bind DN - typically cn=username,base_dn or username@domain */
|
|
/* For Samba AD, we can use username@domain format or userPrincipalName */
|
|
/* Here we'll try simple bind with CN format first */
|
|
snprintf(bind_dn, sizeof(bind_dn), "cn=%s,%s", username, base_dn);
|
|
|
|
/* Attempt to bind */
|
|
struct berval cred;
|
|
cred.bv_val = (char *)password;
|
|
cred.bv_len = strlen(password);
|
|
|
|
rc = ldap_sasl_bind_s(ld, bind_dn, LDAP_SASL_SIMPLE, &cred,
|
|
NULL, NULL, NULL);
|
|
|
|
if (rc != LDAP_SUCCESS) {
|
|
/* Try alternative format: username@domain */
|
|
/* Extract domain from base_dn (DC=example,DC=com -> example.com) */
|
|
char domain[256] = {0};
|
|
const char *dc = strstr(base_dn, "DC=");
|
|
if (dc) {
|
|
const char *ptr = dc + 3;
|
|
char *out = domain;
|
|
while (*ptr && (out - domain) < sizeof(domain) - 1) {
|
|
if (*ptr == ',') {
|
|
ptr++;
|
|
if (strncmp(ptr, "DC=", 3) == 0) {
|
|
*out++ = '.';
|
|
ptr += 3;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
*out++ = *ptr++;
|
|
}
|
|
*out = '\0';
|
|
}
|
|
|
|
if (strlen(domain) > 0) {
|
|
snprintf(bind_dn, sizeof(bind_dn), "%s@%s", username, domain);
|
|
rc = ldap_sasl_bind_s(ld, bind_dn, LDAP_SASL_SIMPLE, &cred,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
ldap_unbind_ext_s(ld, NULL, NULL);
|
|
|
|
if (rc == LDAP_SUCCESS) {
|
|
LOG(LOG_DEBUG, "LDAP bind successful for: %s", username);
|
|
return 0;
|
|
} else {
|
|
LOG(LOG_DEBUG, "LDAP bind failed: %s", ldap_err2string(rc));
|
|
return -1;
|
|
}
|
|
}
|