summarylogtreecommitdiffstats
path: root/tftp-hpa-add-destructive-mode.patch
blob: b21c335500beb433e9296142d88fde2ec737792c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
diff -Nwrau tftp-hpa-5.2/tftpd/tftpd.c a/tftpd/tftpd.c
--- tftp-hpa-5.2/tftpd/tftpd.c	2011-12-11 23:13:52.000000000 +0100
+++ a/tftpd/tftpd.c	2016-02-25 15:12:19.023457282 +0100
@@ -49,6 +49,10 @@
 #include <limits.h>
 #include <syslog.h>

+#ifdef WITH_REGEX
+#include <regex.h>
+#endif
+
 #include "common/tftpsubs.h"
 #include "recvfrom.h"
 #include "remap.h"
@@ -110,6 +114,10 @@
 struct formats;
 #ifdef WITH_REGEX
 static struct rule *rewrite_rules = NULL;
+
+static const char *selfdestruct_pattern;
+static regex_t selfdestruct_re;
+static int selfdestruct(const char *filename);
 #endif

 int tftp(struct tftphdr *, int);
@@ -178,6 +186,19 @@

     return rulep;
 }
+
+static int selfdestruct(const char *filename)
+{
+    if (!selfdestruct_pattern) {
+        return 0;
+    }
+    const char *tmp = strchr(filename, '/');
+    if (tmp) {
+        filename = tmp + 1;
+    }
+
+    return !regexec(&selfdestruct_re, filename, 0, NULL, 0);
+}
 #endif

 /*
@@ -324,6 +345,7 @@

 enum long_only_options {
     OPT_VERBOSITY	= 256,
+    OPT_SELFDESTRUCT_PATTERN,
 };

 static struct option long_options[] = {
@@ -347,6 +369,8 @@
     { "port-range",  1, NULL, 'R' },
     { "map-file",    1, NULL, 'm' },
     { "pidfile",     1, NULL, 'P' },
+    { "selfdestruct-pattern",
+                     1, NULL, OPT_SELFDESTRUCT_PATTERN },
     { NULL, 0, NULL, 0 }
 };
 static const char short_options[] = "46cspvVlLa:B:u:U:r:t:T:R:m:P:";
@@ -493,6 +517,19 @@
             }
             rewrite_file = optarg;
             break;
+        case OPT_SELFDESTRUCT_PATTERN:
+            {
+                int errcode = regcomp(&selfdestruct_re, optarg,
+                                      REG_EXTENDED|REG_NOSUB);
+                if (errcode != 0) {
+                    char errbuf[BUFSIZ];
+                    regerror(errcode, &selfdestruct_re, errbuf, BUFSIZ);
+                    syslog(LOG_ERR, "Bad selfdestruct regex: %s\n", errbuf);
+                    exit(EX_CONFIG);
+                }
+                selfdestruct_pattern = optarg;
+            }
+            break;
 #endif
         case 'v':
             verbosity++;
@@ -1498,6 +1535,16 @@
         }
     }

+#ifdef WITH_REGEX
+    if (mode == RRQ && selfdestruct(filename)) {
+        syslog(LOG_NOTICE, "unlinking file %s\n", filename);
+        if (unlink(filename)) {
+            syslog(LOG_WARNING, "error unlinking \"%s\": %s\n",
+                   filename, strerror(errno));
+        }
+    }
+#endif
+
     if (fstat(fd, &stbuf) < 0)
         exit(EX_OSERR);         /* This shouldn't happen */