Hello,
recently I needed to configure ProFTPd to authenticate users in Microsoft AD
domain. I think it's a well-known fact that AD LDAP directory by default
does not contain any "uidNumber" and "gidNumber" (or equivalent) attribute.
If you configure system-wide authentication to AD with sssd (according to
many guides available on the net), it can use a special algorithm to map
"objectSid" values present in the AD directory to UIDs and GIDs, therefore
"producing" specific UID/GID values for each user.
However, ProFTPd's mod_ldap module cannot use this information and therefore
one needs to force all users logging in via AD to the same LDAPDefaultUID
and LDAPDefaultGID values. This is not always acceptable. In my case, I
needed the users logging in via FTP to have the same UID/GID values as the
ones provided to them via sssd when logging in interactively (otherwise they
wouldn't be able to write to their home directories!). I wonder that nobody
has written nowhere about this obvious (and very common) problem and didn't
suggest any solution for it.
Therefore I created a simple patch to mod_ldap.c, allowing to use a special
value "auto" for LDAPDefaultUID or LDAPDefaultGID directive in config file
(actually the value "auto" is internally converted to UID/GID equal to -2,
so one can obtain the same result specifying -2 as the value for
LDAPDefaultUID/LDAPDefaultGID). If LDAPDefaultUID or LDAPDefaultGID is set
to "auto", the correct value of UID or GID is obtained via getpwnam() call
from the username. This is enough to make use of the mapping provided by
sssd.
The patch is enclosed. It is a patch against the current version on Github
(it should work also with 1.3.7d), although I haven't tested it with that
version. My ProFTPd is version 1.3.4a, so I initially patched mod_ldap
distributed with that version, which is a bit different. But the patch is so
simple that I hope I have changed it properly for the new version :).
I don't know what is the correct way to submit this for considering to be
included in the distribution, so I'm simply sending the patch for your use
in whatever way appropriate.
--
Regards,
Jaroslaw Rafa
[email protected]
--
"In a million years, when kids go to school, they're gonna know: once there
was a Hushpuppy, and she lived with her daddy in the Bathtub."
*** mod_ldap.orig.c 2022-05-25 23:01:45.470693692 +0200
--- mod_ldap.c 2022-05-25 23:03:13.619453377 +0200
***************
*** 44,49 ****
--- 44,52 ----
# include <sasl/sasl.h>
#endif /* HAVE_SASL_SASL_H */
+ #include <sys/types.h>
+ #include <pwd.h>
+
extern xaset_t *server_list;
module ldap_module;
***************
*** 856,862 ****
return NULL;
}
! pw->pw_uid = ldap_defaultuid;
++i;
(void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION,
--- 859,874 ----
return NULL;
}
! if (ldap_defaultuid == (uid_t) -2) {
! if ((char *)pw->pw_name == '\0') {
! (void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION, "user name not set - can't lookup UID value!");
! return NULL;
! } else {
! pw->pw_uid = getpwnam(pw->pw_name)->pw_uid;
! }
! } else {
! pw->pw_uid = ldap_defaultuid;
! }
++i;
(void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION,
***************
*** 875,881 ****
return NULL;
}
! pw->pw_gid = ldap_defaultgid;
++i;
(void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION,
--- 887,902 ----
return NULL;
}
! if (ldap_defaultgid == (gid_t) -2) {
! if ((char *)pw->pw_name == '\0') {
! (void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION, "user name not set - can't lookup GID value!");
! return NULL;
! } else {
! pw->pw_gid = getpwnam(pw->pw_name)->pw_gid;
! }
! } else {
! pw->pw_gid = ldap_defaultgid;
! }
++i;
(void) pr_log_writefile(ldap_logfd, MOD_LDAP_VERSION,
***************
*** 971,977 ****
} else if (strcasecmp(attrs[i], ldap_attr_uidnumber) == 0) {
if (ldap_forcedefaultuid == TRUE &&
ldap_defaultuid != (uid_t) -1) {
! pw->pw_uid = ldap_defaultuid;
} else {
pw->pw_uid = (uid_t) strtoul(LDAP_VALUE(values, 0), NULL, 10);
--- 992,1002 ----
} else if (strcasecmp(attrs[i], ldap_attr_uidnumber) == 0) {
if (ldap_forcedefaultuid == TRUE &&
ldap_defaultuid != (uid_t) -1) {
! if (ldap_defaultuid == (uid_t) -2) {
! pw->pw_uid = getpwnam(pw->pw_name)->pw_uid;
! } else {
! pw->pw_uid = ldap_defaultuid;
! }
} else {
pw->pw_uid = (uid_t) strtoul(LDAP_VALUE(values, 0), NULL, 10);
***************
*** 980,986 ****
} else if (strcasecmp(attrs[i], ldap_attr_gidnumber) == 0) {
if (ldap_forcedefaultgid == TRUE &&
ldap_defaultgid != (gid_t) -1) {
! pw->pw_gid = ldap_defaultgid;
} else {
pw->pw_gid = (gid_t) strtoul(LDAP_VALUE(values, 0), NULL, 10);
--- 1005,1015 ----
} else if (strcasecmp(attrs[i], ldap_attr_gidnumber) == 0) {
if (ldap_forcedefaultgid == TRUE &&
ldap_defaultgid != (gid_t) -1) {
! if (ldap_defaultgid == (gid_t) -2) {
! pw->pw_gid = getpwnam(pw->pw_name)->pw_gid;
! } else {
! pw->pw_gid = ldap_defaultgid;
! }
} else {
pw->pw_gid = (gid_t) strtoul(LDAP_VALUE(values, 0), NULL, 10);
***************
*** 2862,2872 ****
c = add_config_param(cmd->argv[0], 1, NULL);
c->argv[0] = pcalloc(c->pool, sizeof(uid_t));
! if (pr_str2uid(cmd->argv[1], &uid) < 0) {
! CONF_ERROR(cmd, "LDAPDefaultUID: UID argument must be numeric");
! }
! *((uid_t *) c->argv[0]) = uid;
return PR_HANDLED(cmd);
}
--- 2891,2905 ----
c = add_config_param(cmd->argv[0], 1, NULL);
c->argv[0] = pcalloc(c->pool, sizeof(uid_t));
! if (strcmp(cmd->argv[1], "auto")==0) {
! *((uid_t *) c->argv[0]) = -2;
! } else {
! if (pr_str2uid(cmd->argv[1], &uid) < 0) {
! CONF_ERROR(cmd, "LDAPDefaultUID: UID argument must be numeric");
! }
! *((uid_t *) c->argv[0]) = uid;
! }
return PR_HANDLED(cmd);
}
***************
*** 2880,2890 ****
c = add_config_param(cmd->argv[0], 1, NULL);
c->argv[0] = pcalloc(c->pool, sizeof(gid_t));
! if (pr_str2gid(cmd->argv[1], &gid) < 0) {
! CONF_ERROR(cmd, "LDAPDefaultGID: GID argument must be numeric");
! }
! *((gid_t *) c->argv[0]) = gid;
return PR_HANDLED(cmd);
}
--- 2913,2927 ----
c = add_config_param(cmd->argv[0], 1, NULL);
c->argv[0] = pcalloc(c->pool, sizeof(gid_t));
! if (strcmp(cmd->argv[1], "auto")==0) {
! *((gid_t *) c->argv[0]) = -2;
! } else {
! if (pr_str2gid(cmd->argv[1], &gid) < 0) {
! CONF_ERROR(cmd, "LDAPDefaultGID: GID argument must be numeric");
! }
! *((gid_t *) c->argv[0]) = gid;
! }
return PR_HANDLED(cmd);
}
_______________________________________________
ProFTPD Developers List
<[email protected]>
https://lists.sourceforge.net/lists/listinfo/proftp-devel