If this is a valid plugin return full path name, otherwise NULL */
| 1843 | |
| 1844 | /* If this is a valid plugin return full path name, otherwise NULL */ |
| 1845 | static const char *plugin_fullpath(const tal_t *ctx, const char *dir, |
| 1846 | const char *basename) |
| 1847 | { |
| 1848 | struct stat st; |
| 1849 | const char *fullname; |
| 1850 | struct utf8_state utf8 = UTF8_STATE_INIT; |
| 1851 | |
| 1852 | for (size_t i = 0; basename[i]; i++) { |
| 1853 | if (!utf8_decode(&utf8, basename[i])) |
| 1854 | continue; |
| 1855 | /* Not valid UTF8? Let's not go there... */ |
| 1856 | if (errno != 0) |
| 1857 | return NULL; |
| 1858 | if (utf8.used_len != 1) |
| 1859 | continue; |
| 1860 | if (!cispunct(utf8.c)) |
| 1861 | continue; |
| 1862 | if (utf8.c != '-' && utf8.c != '_' && utf8.c != '.') |
| 1863 | return NULL; |
| 1864 | } |
| 1865 | |
| 1866 | fullname = path_join(ctx, dir, basename); |
| 1867 | if (stat(fullname, &st) != 0) |
| 1868 | return tal_free(fullname); |
| 1869 | /* Only regular files please (or symlinks to such: stat not lstat!) */ |
| 1870 | if ((st.st_mode & S_IFMT) != S_IFREG) |
| 1871 | return tal_free(fullname); |
| 1872 | /* Must be executable by someone. */ |
| 1873 | if (!(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) |
| 1874 | return tal_free(fullname); |
| 1875 | |
| 1876 | /* Someone actually runs this on NTFS, where everything apparently is |
| 1877 | * executable! This prevents the most obvious damage. */ |
| 1878 | if (streq(basename, "README.md")) |
| 1879 | return tal_free(fullname); |
| 1880 | |
| 1881 | return fullname; |
| 1882 | } |
| 1883 | |
| 1884 | char *add_plugin_dir(struct plugins *plugins, const char *dir, bool error_ok) |
| 1885 | { |
no test coverage detected