/** * Wrapper for the smbc_getxattr() smbclient function. From libsmbclient.h * @author [email protected], [email protected] * * @param uri The smb url of the file or directory to get extended * attributes for. * * @param name The name of an attribute to be retrieved. Names are of * one of the following forms: * * system.nt_sec_desc.<attribute name> * system.nt_sec_desc.* * system.nt_sec_desc.*+ */ static PyObject * Context_getxattr (Context *self, PyObject *args) { int ret; char *uri = NULL; char *name = NULL; char *buffer = NULL; static smbc_getxattr_fn fn; // smbc_getxattr takes two string parameters if (!PyArg_ParseTuple (args, "ss", &uri, &name)) { return NULL; } /* The security descriptor string returned by this call will vary depending on the requested attribute * A call with system.nt_sec_desc.* will return the longest string which would be in the following format: * * REVISION:<revision number>,OWNER:<sid>,GROUP:<sid>,ACL:<sid>:<type>/<flags>/<mask> * * There could be multiple ACL entries up to a reasonable maximum of 1820. * * <revision number> : 3 chars * <sid> : 184 chars * <type>: 1 char * <flags>: 3 chars * <mask>: 10 chars * * The maximum size of the security descriptor string returned can be * derived as follows (includes space for terminating null): * Sec Desc = 13 + 2 x (7 + <sid>) + 1820 * (5 + <acl>) = 375315 * * References: https://msdn.microsoft.com/en-us/library/cc246018.aspx * https://technet.microsoft.com/en-us/library/cc961995.aspx * https://technet.microsoft.com/en-us/library/cc961986.aspx */ size_t size = 375315; buffer = (char *)malloc (size); if(!buffer) return PyErr_NoMemory (); bzero(buffer, size); errno = 0; fn = smbc_getFunctionGetxattr(self->context); ret = (*fn)(self->context, uri, name, buffer, size); if (ret < 0) { pysmbc_SetFromErrno (); free(buffer); return NULL; } PyObject *value = PyUnicode_FromString(buffer); free(buffer); return value; }
int smbc_lgetxattr(const char *fname, const char *name, const void *value, size_t size) { return smbc_getFunctionGetxattr(statcont)(statcont, fname, name, value, size); }
int smbc_fgetxattr(int fd, const char *name, const void *value, size_t size) { SMBCFILE * file = find_fd(fd); if (file == NULL) { errno = EBADF; return -1; } return smbc_getFunctionGetxattr(statcont)(statcont, file->fname, name, value, size); }
static smbresultlist* browse(SMBCCTX *ctx, char *path, int maxdepth, int depth) { SMBCFILE *fd; struct smbc_dirent *dirent; char fullpath[2560] = ""; char acl[1024] = ""; int aclret; char mode[128] = ""; int moderet; smbresultlist *thisresults = NULL; smbresultlist *subresults = NULL; //Try and get a directory listing of the object we just opened. //This could be a workgroup, server, share, or directory and //we'll get the full listing. If it doesn't work, return our error. //Errors will happen a lot in normal usage due to access denied. if ((fd = smbc_getFunctionOpendir(ctx)(ctx, path)) == NULL) { smbresult *tmp = createSMBResultEmpty(); parse_smburl(path, &tmp->host, &tmp->share, &tmp->object); tmp->statuscode = errno; smbresultlist_push(&thisresults, tmp); return thisresults; } //Get the current entity of the directory item we're working on. while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, fd)) != NULL) { smbresult *thisresult = createSMBResultEmpty(); //Check to see if what we're working on is blank, or one of the //special directory characters. If so, skip them. if(strcmp(dirent->name, "") == 0) continue; if(strcmp(dirent->name, ".") == 0) continue; if(strcmp(dirent->name, "..") == 0) continue; //Create the full path for this object by concating it with the //parent path. sprintf(fullpath, "%s/%s", path, dirent->name); //Parse out the various parts of the path for pretty output. parse_smburl(fullpath, &thisresult->host, &thisresult->share, &thisresult->object); //Set the type so we have it thisresult->type = dirent->smbc_type; //Get the "dos_attr.mode" extended attribute which is the file permissions. moderet = smbc_getFunctionGetxattr(ctx)(ctx, fullpath, "system.dos_attr.mode", &mode, sizeof(mode)); if(moderet == -1 && errno == 13) { thisresult->mode = -1; } else { //The ACL is returned as a string pointer, but we need to convert it to a long so we can //do binary comparison on the settings eventually. thisresult->mode = strtol(acl, NULL, 16); } //Get the ACL ACEs for the NTFS permissions. The + is so we lookup SIDs to names aclret = smbc_getFunctionGetxattr(ctx)(ctx, fullpath, "system.nt_sec_desc.acl.*+", acl, sizeof(acl)); if(aclret < 0) { char permerrbuf[100]; sprintf(permerrbuf, "Unable to pull permissions (%d): %s", errno, strerror(errno)); thisresult->acl = strdup(permerrbuf); thisresult->statuscode = errno; } else { thisresult->acl = strdup(acl); } smbresultlist_push(&thisresults, thisresult); //If we have a directory or share we want to recurse to our max depth if(depth < maxdepth) { switch (thisresult->type) { case SMBC_FILE_SHARE: case SMBC_DIR: subresults = browse(ctx, fullpath, maxdepth, depth++); smbresultlist_merge(&thisresults, &subresults); } } } //Try to close the directory that we had opened. If it failed, it'll return > 0. if(smbc_getFunctionClosedir(ctx)(ctx, fd) > 0) { smbresult *tmp = createSMBResultEmpty(); parse_smburl(path, &tmp->host, &tmp->share, &tmp->object); tmp->statuscode = errno; smbresultlist_push(&thisresults, tmp); } //Finally, we're done, lets return to the user. return thisresults; }