-int is_safe_path(const char *file)
-{
- char *p;
- const char *f;
- char x;
- struct stat s;
- char l[MAXBUFSIZE];
-
- if(*file != '/')
- {
- syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
- return 0;
- }
-
- p = strrchr(file, '/');
-
- if(p == file) /* It's in the root */
- p++;
-
- x = *p;
- *p = '\0';
-
- f = file;
-check1:
- if(lstat(f, &s) < 0)
- {
- syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
- return 0;
- }
-
- if(s.st_uid != geteuid())
- {
- syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
- f, s.st_uid, geteuid());
- return 0;
- }
-
- if(S_ISLNK(s.st_mode))
- {
- syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
- f);
-
- if(readlink(f, l, MAXBUFSIZE) < 0)
- {
- syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
- return 0;
- }
-
- f = l;
- goto check1;
- }
-
- *p = x;
- f = file;
-
-check2:
- if(lstat(f, &s) < 0 && errno != ENOENT)
- {
- syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
- return 0;
- }
-
- if(errno == ENOENT)
- return 1;
-
- if(s.st_uid != geteuid())
- {
- syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"),
- f, s.st_uid, geteuid());
- return 0;
- }
-
- if(S_ISLNK(s.st_mode))
- {
- syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
- f);
-
- if(readlink(f, l, MAXBUFSIZE) < 0)
- {
- syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
- return 0;
- }
-
- f = l;
- goto check2;
- }
-
- if(s.st_mode & 0007)
- {
- /* Accessible by others */
- syslog(LOG_ERR, _("`%s' has unsecure permissions"),
- f);
- return 0;
- }
-
- return 1;
+static void disable_old_keys(const char *filename) {
+ char tmpfile[PATH_MAX] = "";
+ char buf[1024];
+ bool disabled = false;
+ FILE *r, *w;
+
+ r = fopen(filename, "r");
+ if(!r)
+ return;
+
+ snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename);
+
+ w = fopen(tmpfile, "w");
+
+ while(fgets(buf, sizeof buf, r)) {
+ if(!strncmp(buf, "-----BEGIN RSA", 14)) {
+ buf[11] = 'O';
+ buf[12] = 'L';
+ buf[13] = 'D';
+ disabled = true;
+ }
+ else if(!strncmp(buf, "-----END RSA", 12)) {
+ buf[ 9] = 'O';
+ buf[10] = 'L';
+ buf[11] = 'D';
+ disabled = true;
+ }
+ if(w && fputs(buf, w) < 0) {
+ disabled = false;
+ break;
+ }
+ }
+
+ if(w)
+ fclose(w);
+ fclose(r);
+
+ if(!w && disabled) {
+ fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+ return;
+ }
+
+ if(disabled) {
+#ifdef HAVE_MINGW
+ // We cannot atomically replace files on Windows.
+ char bakfile[PATH_MAX] = "";
+ snprintf(bakfile, sizeof bakfile, "%s.bak", filename);
+ if(rename(filename, bakfile) || rename(tmpfile, filename)) {
+ rename(bakfile, filename);
+#else
+ if(rename(tmpfile, filename)) {
+#endif
+ fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
+ } else {
+#ifdef HAVE_MINGW
+ unlink(bakfile);
+#endif
+ fprintf(stderr, "Warning: old key(s) found and disabled.\n");
+ }
+ }
+
+ unlink(tmpfile);