diff options
Diffstat (limited to 'source3/libsmb/libsmbclient.c')
-rw-r--r-- | source3/libsmb/libsmbclient.c | 311 |
1 files changed, 95 insertions, 216 deletions
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 41a6755953..440527cd9d 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -52,87 +52,6 @@ extern BOOL in_client; */ static int smbc_initialized = 0; -static int -hex2int( unsigned int _char ) -{ - if ( _char >= 'A' && _char <='F') - return _char - 'A' + 10; - if ( _char >= 'a' && _char <='f') - return _char - 'a' + 10; - if ( _char >= '0' && _char <='9') - return _char - '0'; - return -1; -} - -static void -decode_urlpart(char *segment, size_t sizeof_segment) -{ - int old_length = strlen(segment); - int new_length = 0; - int new_length2 = 0; - int i = 0; - pstring new_segment; - char *new_usegment = 0; - - if ( !old_length ) { - return; - } - - /* make a copy of the old one */ - new_usegment = (char*)malloc( old_length * 3 + 1 ); - - while( i < old_length ) { - int bReencode = False; - unsigned char character = segment[ i++ ]; - if ((character <= ' ') || (character > 127)) - bReencode = True; - - new_usegment [ new_length2++ ] = character; - if (character == '%' ) { - int a = i+1 < old_length ? hex2int( segment[i] ) : -1; - int b = i+1 < old_length ? hex2int( segment[i+1] ) : -1; - if ((a == -1) || (b == -1)) { /* Only replace if sequence is valid */ - /* Contains stray %, make sure to re-encode! */ - bReencode = True; - } else { - /* Valid %xx sequence */ - character = a * 16 + b; /* Replace with value of %dd */ - if (!character) - break; /* Stop at %00 */ - - new_usegment [ new_length2++ ] = (unsigned char) segment[i++]; - new_usegment [ new_length2++ ] = (unsigned char) segment[i++]; - } - } - if (bReencode) { - unsigned int c = character / 16; - new_length2--; - new_usegment [ new_length2++ ] = '%'; - - c += (c > 9) ? ('A' - 10) : '0'; - new_usegment[ new_length2++ ] = c; - - c = character % 16; - c += (c > 9) ? ('A' - 10) : '0'; - new_usegment[ new_length2++ ] = c; - } - - new_segment [ new_length++ ] = character; - } - new_segment [ new_length ] = 0; - - free(new_usegment); - - /* realloc it with unix charset */ - pull_utf8_allocate((void**)&new_usegment, new_segment); - - /* this assumes (very safely) that removing %aa sequences - only shortens the string */ - strncpy(segment, new_usegment, sizeof_segment); - - free(new_usegment); -} - /* * Function to parse a path and turn it into components * @@ -178,7 +97,7 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, p += 2; /* Skip the // or \\ */ if (*p == (char)0) - goto decoding; + return 0; if (*p == '/') { @@ -239,7 +158,7 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, } - if (*p == (char)0) goto decoding; /* That's it ... */ + if (*p == (char)0) return 0; /* That's it ... */ if (!next_token(&p, share, "/", sizeof(fstring))) { @@ -248,16 +167,9 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, } pstrcpy(path, p); - + all_string_sub(path, "/", "\\", 0); - decoding: - decode_urlpart(path, sizeof(pstring)); - decode_urlpart(server, sizeof(fstring)); - decode_urlpart(share, sizeof(fstring)); - decode_urlpart(user, sizeof(fstring)); - decode_urlpart(password, sizeof(fstring)); - return 0; } @@ -355,16 +267,15 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv) */ SMBCSRV *smbc_server(SMBCCTX *context, - const char *server, const char *share, - fstring workgroup, fstring username, - fstring password) + char *server, char *share, + char *workgroup, char *username, + char *password) { SMBCSRV *srv=NULL; int auth_called = 0; struct cli_state c; struct nmb_name called, calling; - char *p; - const char *server_n = server; + char *p, *server_n = server; fstring group; pstring ipenv; struct in_addr ip; @@ -818,6 +729,27 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file) } + if (!file->file) { + + return context->closedir(context, file); + + } + + if (!cli_close(&file->srv->cli, file->cli_fd)) { + DEBUG(3, ("cli_close failed on %s. purging server.\n", + file->fname)); + /* Deallocate slot and remove the server + * from the server cache if unused */ + errno = smbc_errno(context, &file->srv->cli); + srv = file->srv; + DLIST_REMOVE(context->internal->_files, file); + SAFE_FREE(file->fname); + SAFE_FREE(file); + context->callbacks.remove_unused_server_fn(context, srv); + + return -1; + } + DLIST_REMOVE(context->internal->_files, file); SAFE_FREE(file->fname); SAFE_FREE(file); @@ -1071,16 +1003,12 @@ static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int case SEEK_END: if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, NULL, &size, NULL, NULL, - NULL, NULL, NULL)) - { - SMB_BIG_UINT b_size = size; - if (!cli_getattrE(&file->srv->cli, file->cli_fd, NULL, &b_size, NULL, NULL, - NULL)) - { + NULL, NULL, NULL) && + !cli_getattrE(&file->srv->cli, file->cli_fd, NULL, &size, NULL, NULL, + NULL)) { + errno = EINVAL; return -1; - } else - size = b_size; } file->offset = size + offset; break; @@ -1278,15 +1206,12 @@ static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st) } if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, - &mode, &size, &c_time, &a_time, &m_time, NULL, &ino)) { - SMB_BIG_UINT b_size = size; - if (!cli_getattrE(&file->srv->cli, file->cli_fd, - &mode, &b_size, &c_time, &a_time, &m_time)) { + &mode, &size, &c_time, &a_time, &m_time, NULL, &ino) && + !cli_getattrE(&file->srv->cli, file->cli_fd, + &mode, &size, &c_time, &a_time, &m_time)) { errno = EINVAL; return -1; - } else - size = b_size; } @@ -1339,13 +1264,6 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint { struct smbc_dirent *dirent; int size; - char *u_name = NULL, *u_comment = NULL; - size_t u_name_len = 0, u_comment_len = 0; - - if (name) - u_name_len = push_utf8_allocate(&u_name, name); - if (comment) - u_comment_len = push_utf8_allocate(&u_comment, comment); /* * Allocate space for the dirent, which must be increased by the @@ -1353,7 +1271,8 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint * The null on the name is already accounted for. */ - size = sizeof(struct smbc_dirent) + u_name_len + u_comment_len + 1; + size = sizeof(struct smbc_dirent) + (name?strlen(name):0) + + (comment?strlen(comment):0) + 1; dirent = malloc(size); @@ -1402,17 +1321,14 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint dir->dir_end->dirent = dirent; dirent->smbc_type = type; - dirent->namelen = u_name_len; - dirent->commentlen = u_comment_len; + dirent->namelen = (name?strlen(name):0); + dirent->commentlen = (comment?strlen(comment):0); dirent->dirlen = size; - strncpy(dirent->name, (u_name?u_name:""), dirent->namelen + 1); + strncpy(dirent->name, (name?name:""), dirent->namelen + 1); dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); - strncpy(dirent->comment, (u_comment?u_comment:""), dirent->commentlen + 1); - - SAFE_FREE(u_comment); - SAFE_FREE(u_name); + strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); return 0; @@ -1476,47 +1392,9 @@ dir_list_fn(file_info *finfo, const char *mask, void *state) } - -/* Return the IP address and workgroup of a master browser on the - network. */ - -static BOOL find_master_ip_bcast(pstring workgroup, struct in_addr *server_ip) -{ - struct in_addr *ip_list; - int i, count; - - /* Go looking for workgroups by broadcasting on the local network */ - - if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { - return False; - } - - for (i = count-1; i < count; i++) { - static fstring name; - - DEBUG(0, ("name_status_find %d %s\n", i, inet_ntoa(ip_list[i]))); - - if (!name_status_find("*", 0, 0x1d, ip_list[i], name)) - continue; - - if (!find_master_ip(name, server_ip)) - continue; - - pstrcpy(workgroup, name); - - DEBUG(4, ("found master browser %s, %s\n", - name, inet_ntoa(ip_list[i]))); - - return True; - } - - return False; -} - static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) { - fstring server, share, user, password; - pstring workgroup; + fstring server, share, user, password, workgroup; pstring path; SMBCSRV *srv = NULL; SMBCFILE *dir = NULL; @@ -1524,29 +1402,29 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) if (!context || !context->internal || !context->internal->_initialized) { - DEBUG(4, ("no valid context\n")); + errno = EINVAL; return NULL; } if (!fname) { - DEBUG(4, ("no valid fname\n")); + errno = EINVAL; return NULL; + } if (smbc_parse_path(context, fname, server, share, path, user, password)) { - DEBUG(4, ("no valid path\n")); + errno = EINVAL; return NULL; - } - DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' path='%s'\n", fname, server, share, path)); + } if (user[0] == (char)0) fstrcpy(user, context->user); - pstrcpy(workgroup, context->workgroup); + fstrcpy(workgroup, context->workgroup); dir = malloc(sizeof(*dir)); @@ -1567,56 +1445,64 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) dir->dir_list = dir->dir_next = dir->dir_end = NULL; if (server[0] == (char)0) { - struct in_addr server_ip; - DEBUG(4, ("empty server\n")); + if (share[0] != (char)0 || path[0] != (char)0) { - DEBUG(4,("share %d path %d\n", share[0], path[0])); + errno = EINVAL; if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); } return NULL; + } /* We have server and share and path empty ... so list the workgroups */ /* first try to get the LMB for our workgroup, and if that fails, */ /* try the DMB */ - pstrcpy(workgroup, lp_workgroup()); + if (!(resolve_name(context->workgroup, &rem_ip, 0x1d) || + resolve_name(context->workgroup, &rem_ip, 0x1b))) { + + errno = EINVAL; /* Something wrong with smb.conf? */ + return NULL; - if (!find_master_ip(lp_workgroup(), &server_ip)) { - DEBUG(4, ("Unable to find master browser for workgroup %s\n", - workgroup)); - if (!find_master_ip_bcast(workgroup, &server_ip)) { - DEBUG(4, ("Unable to find master browser by " - "broadcast\n")); - errno = ENOENT; + } + + dir->dir_type = SMBC_WORKGROUP; + + /* find the name of the server ... */ + + if (!name_status_find("*", 0, 0, rem_ip, server)) { + + DEBUG(0,("Could not get the name of local/domain master browser for server %s\n", server)); + errno = EINVAL; return NULL; - } - } - - /* - * Get a connection to IPC$ on the server if we do not already have one - */ - - srv = smbc_server(context, inet_ntoa(server_ip), "IPC$", workgroup, user, password); - - if (!srv) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - return NULL; - } - + + } + + /* + * Get a connection to IPC$ on the server if we do not already have one + */ + + srv = smbc_server(context, server, "IPC$", workgroup, user, password); + + if (!srv) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + + return NULL; + + } + dir->srv = srv; - dir->dir_type = SMBC_WORKGROUP; /* Now, list the stuff ... */ - if (!cli_NetServerEnum(&srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_fn, + if (!cli_NetServerEnum(&srv->cli, workgroup, 0x80000000, list_fn, (void *)dir)) { if (dir) { @@ -1674,7 +1560,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) srv = smbc_server(context, buserver, "IPC$", workgroup, user, password); if (!srv) { - DEBUG(0, ("got no contact to IPC$\n")); + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -2172,7 +2058,6 @@ static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname) static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) { - off_t ret_val; /* Squash warnings about cast */ if (!context || !context->internal || !context->internal->_initialized) { @@ -2196,11 +2081,7 @@ static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) } - /* - * We return the pointer here as the offset - */ - ret_val = (int)dir->dir_next; - return ret_val; + return (off_t) dir->dir_next; } @@ -2240,9 +2121,8 @@ struct smbc_dir_list *smbc_check_dir_ent(struct smbc_dir_list *list, static int smbc_lseekdir_ctx(SMBCCTX *context, SMBCFILE *dir, off_t offset) { - long int l_offset = offset; /* Handle problems of size */ - struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; - struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; + struct smbc_dirent *dirent = (struct smbc_dirent *)offset; + struct smbc_dir_list *list_ent = NULL; if (!context || !context->internal || !context->internal->_initialized) { @@ -2692,7 +2572,7 @@ SMBCCTX * smbc_init_context(SMBCCTX * context) /* Do we still need this ? */ DEBUGLEVEL = 10; - setup_logging( "libsmbclient", True); + setup_logging( "libsmbclient", False); /* Here we would open the smb.conf file if needed ... */ @@ -2760,8 +2640,8 @@ SMBCCTX * smbc_init_context(SMBCCTX * context) slprintf(context->netbios_name, 16, "smbc%s%d", context->user, pid); } } - - DEBUG(1, ("Using netbios name %s.\n", context->netbios_name)); + DEBUG(0,("Using netbios name %s.\n", context->netbios_name)); + if (!context->workgroup) { if (lp_workgroup()) { @@ -2772,8 +2652,7 @@ SMBCCTX * smbc_init_context(SMBCCTX * context) context->workgroup = strdup("samba"); } } - - DEBUG(1, ("Using workgroup %s.\n", context->workgroup)); + DEBUG(0,("Using workgroup %s.\n", context->workgroup)); /* shortest timeout is 1 second */ if (context->timeout > 0 && context->timeout < 1000) |