| 146 | } |
| 147 | |
| 148 | static const char *path_ok(const char *directory, struct hostinfo *hi) |
| 149 | { |
| 150 | static char rpath[PATH_MAX]; |
| 151 | static char interp_path[PATH_MAX]; |
| 152 | size_t rlen; |
| 153 | const char *path; |
| 154 | const char *dir; |
| 155 | unsigned enter_repo_flags; |
| 156 | |
| 157 | dir = directory; |
| 158 | |
| 159 | if (daemon_avoid_alias(dir)) { |
| 160 | logerror("'%s': aliased", dir); |
| 161 | return NULL; |
| 162 | } |
| 163 | |
| 164 | if (*dir == '~') { |
| 165 | if (!user_path) { |
| 166 | logerror("'%s': User-path not allowed", dir); |
| 167 | return NULL; |
| 168 | } |
| 169 | if (*user_path) { |
| 170 | /* Got either "~alice" or "~alice/foo"; |
| 171 | * rewrite them to "~alice/%s" or |
| 172 | * "~alice/%s/foo". |
| 173 | */ |
| 174 | int namlen, restlen = strlen(dir); |
| 175 | const char *slash = strchr(dir, '/'); |
| 176 | if (!slash) |
| 177 | slash = dir + restlen; |
| 178 | namlen = slash - dir; |
| 179 | restlen -= namlen; |
| 180 | loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash); |
| 181 | rlen = snprintf(rpath, sizeof(rpath), "%.*s/%s%.*s", |
| 182 | namlen, dir, user_path, restlen, slash); |
| 183 | if (rlen >= sizeof(rpath)) { |
| 184 | logerror("user-path too large: %s", rpath); |
| 185 | return NULL; |
| 186 | } |
| 187 | dir = rpath; |
| 188 | } |
| 189 | } |
| 190 | else if (interpolated_path && hi->saw_extended_args) { |
| 191 | struct strbuf expanded_path = STRBUF_INIT; |
| 192 | const char *format = interpolated_path; |
| 193 | |
| 194 | if (*dir != '/') { |
| 195 | /* Allow only absolute */ |
| 196 | logerror("'%s': Non-absolute path denied (interpolated-path active)", dir); |
| 197 | return NULL; |
| 198 | } |
| 199 | |
| 200 | while (strbuf_expand_step(&expanded_path, &format)) { |
| 201 | if (skip_prefix(format, "%", &format)) |
| 202 | strbuf_addch(&expanded_path, '%'); |
| 203 | else if (skip_prefix(format, "H", &format)) |
| 204 | strbuf_addbuf(&expanded_path, &hi->hostname); |
| 205 | else if (skip_prefix(format, "CH", &format)) |
no test coverage detected