commit 0e324bf209a78fff0daca2edc14ddbf913717ea2 from: Stefan Sperling date: Fri Sep 01 14:26:17 2023 UTC support special example configs not found in /etc/examples/ Read configs for sshd(8) and smtpd(8) from the live system. These programs are run by default and have no file in the /etc/examples/ directory. Use /etc/npppd/npppd.conf as a fallback if no example is found in /etc/examples. We hope to move npppd.conf to the examples directory in the future. Generate an /etc/motd example with contents as seen after a fresh installation of OpenBSD. commit - 330fe27c7fd1e395ae626f5b6e64cf527f0ae951 commit + 0e324bf209a78fff0daca2edc14ddbf913717ea2 blob - 4011e0f3cb3a14e6359f82f82497db29b47dcd89 blob + b2437ee8b32e25362ea972f30849f0fc1fde5923 --- ctl.c +++ ctl.c @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -819,6 +821,87 @@ call_editor(char *name, char **args, char *z) edit_file(tmpfile, daemons->mode, daemons->propername, args); } +const char *motd_example = "\n\n" + "Welcome to OpenBSD: The proactively secure Unix-like operating system.\n" + "\n" + "Please use the sendbug(1) utility to report bugs in the system.\n" + "Before reporting a bug, please try to reproduce it with the latest\n" + "version of the code. With bug reports, please try to ensure that\n" + "enough information to reproduce the problem is enclosed, and if a\n" + "known fix for it exists, include that as well.\n\n"; + +static size_t +make_example_motd(char *path, size_t size) +{ + char buf[1024]; + int mib[] = { CTL_KERN, KERN_VERSION, INT_MAX }; + int fd; + ssize_t w; + size_t len = 0; + char *eol; + + if (strlcpy(path, "/tmp/nsh-motd-XXXXXXXXXX", size) >= size) + return 0; + + fd = mkstemp(path); + if (fd == -1) + return 0; + + if (sysctl_str(mib, buf, sizeof(buf), 1)) + goto done; + + eol = strchr(buf, '\n'); + if (eol) + *eol = '\0'; + + len = strlen(buf); + + w = write(fd, buf, len); + if (w != len) { + len = 0; + goto done; + } + + len = strlen(motd_example); + w = write(fd, motd_example, len); + if (w != len) + len = 0; +done: + close(fd); + if (len == 0) + unlink(path); + return len; +} + +static size_t +make_example_path(char *path, size_t size, const char *directory, + const char *name) +{ + size_t len; + int ret; + + ret = snprintf(path, size, "%s/%s", directory, name); + if (ret < 0 || (size_t)ret >= size) + return 0; + + /* Snip off rdomain trailer at end of filename. */ + len = strlen(path); + while (len > 0) { + if (path[len - 1] >= '0' && path[len - 1] <= '9') { + path[len - 1] = '\0'; + len--; + } else { + if (path[len - 1] == '.') { + path[len - 1] = '\0'; + len--; + } + break; + } + } + + return len; +} + static void provide_example_config(char *filename) { @@ -826,7 +909,7 @@ provide_example_config(char *filename) char path[PATH_MAX]; char tmpprompt[sizeof(prompt)]; FILE *f = NULL, *example = NULL; - int ret, num; + int num, unlink_example = 0; struct stat sb; size_t len, remain; @@ -846,31 +929,45 @@ provide_example_config(char *filename) if (name == NULL) goto done; - ret = snprintf(path, sizeof(path), "/etc/examples/%s", name); - if (ret < 0 || (size_t)ret >= sizeof(path)) - goto done; - - /* Snip off rdomain trailer at end of filename. */ - len = strlen(path); - while (len > 0) { - if (path[len - 1] >= '0' && path[len - 1] <= '9') { - path[len - 1] = '\0'; - len--; - } else { - if (path[len - 1] == '.') { - path[len - 1] = '\0'; - len--; - } - break; - } + /* + * Most examples are in /etc/examples. However, some daemons + * which are enabled by default have default configs elsewhere. + * In some cases nsh uses different names for configuration files. + */ + if (strncmp(name, "motd", 4) == 0) { + len = make_example_motd(path, sizeof(path)); + if (len > 0) + unlink_example = 1; + } else if (strncmp(name, "sshd.conf", 9) == 0) { + len = make_example_path(path, sizeof(path), + "/etc/ssh", "sshd_config"); + } else if (strncmp(name, "smtpd.conf", 10) == 0) { + len = make_example_path(path, sizeof(path), + "/etc/mail", name); + } else { + len = make_example_path(path, sizeof(path), + "/etc/examples", name); } if (len == 0) goto done; example = fopen(path, "r"); - if (example == NULL) - goto done; + if (example == NULL) { + if (errno != ENOENT) + goto done; + /* XXX npppd.conf should probably be in /etc/examples/ */ + if (strncmp(name, "npppd.conf", 10) != 0) + goto done; + len = make_example_path(path, sizeof(path), + "/etc/npppd", name); + if (len == 0) + goto done; + example = fopen(path, "r"); + if (example == NULL) + goto done; + } + if (fstat(fileno(example), &sb) == -1) goto done; @@ -885,10 +982,8 @@ provide_example_config(char *filename) const char *buf; if ((buf = el_gets(elp, &num)) == NULL) { - if (num == -1) { - ret = -1; + if (num == -1) goto done; - } /* EOF, e.g. ^X or ^D via exit_i() in complete.c */ goto done; } @@ -938,6 +1033,8 @@ done: restoreprompt(); if (example) fclose(example); + if (unlink_example) + unlink(path); } int blob - 2e4977cfe088faa4a96086ab42f1262d2a78f9c1 blob + 1d8310a256e3112a05a6b6ea4c8ab55e5bdb6c6e --- externs.h +++ externs.h @@ -306,6 +306,7 @@ int Ambiguous(void *); /* sysctl.c */ int sysctl_int(int[], int, int); +int sysctl_str(int[], char *, size_t, int); int ipsysctl(int, char *, char *, int); void conf_sysctls(FILE *); blob - b987820def6eb3b7bc042da908ed72a34ef6a2fb blob + 6716dbe41a1d02630972e4686cf7b7884311d8d2 --- sysctl.c +++ sysctl.c @@ -102,6 +102,49 @@ sysctl_int(int mib[], int val, int read) return(old); } +/* + * sysctl_str: get or set a string value + * + * val - value to read or set in sysctl + * read - are we just reading the value (1), or setting it? (0) + */ + +int +sysctl_str(int mib[], char *val, size_t val_size, int read) +{ + void *old = NULL, *new = NULL; + size_t oldlen = 0, newlen = 0; + int i; + + if (read) { + old = val; + oldlen = val_size; + } else { + new = val; + newlen = val_size; + } + + for (i = 0; i < 6; i++) + if (mib[i] == MIB_STOP) + break; + + if (sysctl(mib, i, old, &oldlen, new, newlen) == -1) { + if (!read) { + printf("%% sysctl_str: sysctl: %s\n", strerror(errno)); + } else if (errno != ENOPROTOOPT) { + printf("%% sysctl_str: sysctl: %s\n", strerror(errno)); + for (i = 0; i < 6; i++) { + if (mib[i] == MIB_STOP) + break; + printf("%% mib[%i] == %d\n", i, mib[i]); + } + } + return -1; + } + + return 0; +} + struct sysctltab sysctls[] = { { "ip", PF_INET, iptab, ipsysctls }, { "ip6", PF_INET6, ip6tab, ip6sysctls },