/*
- * is_valid_user_name(), is_valid_group_name() - check the new user/group
- * name for validity;
+ * check user/group names for valid syntax
* return values:
* true - OK
* false - bad name
#include "defines.h"
#include "chkname.h"
+#include "sizeof.h"
#include "string/ctype/isascii.h"
#include "string/strcmp/streq.h"
#include "string/strcmp/strcaseeq.h"
+#include "string/strspn/strrcspn.h"
+#include "string/strtok/stpsep.h"
#include "sysconf.h"
+#define DOMAIN_MAXLEN 255
+#define LABEL_MAXLEN 63
+
+
int allow_bad_names = false;
return is_valid_name (name);
}
+
+
+// Validate a single DNS domain label according to RFC 1035 2.3.1.
+static bool
+is_valid_domain_label(const char *label)
+{
+ if (strlen(label) > LABEL_MAXLEN) {
+ errno = EOVERFLOW;
+ return false;
+ }
+ if (!strspn(label, CTYPE_ALPHA_C) || !strrcspn(label, "-")) {
+ errno = EINVAL;
+ return false;
+ }
+ if (!streq(stpspn(label, CTYPE_ALNUM_C "-"), "")) {
+ errno = EINVAL;
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * Validate a domain name according to RFC 1035 by splitting
+ * it into labels and validating each label individually.
+ */
+static bool
+is_valid_domain_name(const char *domain)
+{
+ char *d;
+ const char *l;
+
+ if (!strcspn(domain, ".")) {
+ errno = EINVAL;
+ return false;
+ }
+
+ if (strlen(domain) + !!strrcspn(domain, ".") > DOMAIN_MAXLEN) {
+ errno = EOVERFLOW;
+ return false;
+ }
+ d = strdupa(domain);
+
+ while (NULL != (l = strsep(&d, "."))) {
+ if (d == NULL && streq(l, "")) // trailing root label
+ break;
+ if (!is_valid_domain_label(l))
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * is_valid_upn - is valid User Principal Name
+ *
+ * Check UPN format (user@domain) for validity.
+ *
+ * This function only validates syntax, not whether the UPN exists
+ * in any authentication system.
+ */
+bool
+is_valid_upn(const char *upn)
+{
+ char *u, *d;
+
+ if (strlen(upn) >= LOGIN_NAME_MAX + STRLEN("@") + DOMAIN_MAXLEN) {
+ errno = EOVERFLOW;
+ return false;
+ }
+ u = strdupa(upn);
+
+ d = stpsep(u, "@");
+ if (d == NULL) {
+ errno = EINVAL;
+ return false;
+ }
+
+ return is_valid_user_name(u) && is_valid_domain_name(d);
+}