Ejemplo n.º 1
0
static bool hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
{
  int depth = 0;
  REGF_HBIN *sub_hbin;
  
  depth++;

  /* get the initial nk record */
  if (!prs_nk_rec("nk_rec", &hbin->ps, depth, nk))
    return false;

  /* fill in values */
  if ( nk->num_values && (nk->values_off!=REGF_OFFSET_NONE) ) 
  {
    sub_hbin = hbin;
    if ( !hbin_contains_offset( hbin, nk->values_off ) ) 
    {
      sub_hbin = lookup_hbin_block( file, nk->values_off );
      if ( !sub_hbin ) 
      {
	/*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing value_list_offset [0x%x]\n", 
	  nk->values_off));*/
	return false;
      }
    }
		
    if(!hbin_prs_vk_records("vk_rec", sub_hbin, depth, nk, file))
      return false;
  }
		
  /* now get subkeys */
  if ( nk->num_subkeys && (nk->subkeys_off!=REGF_OFFSET_NONE) ) 
  {
    sub_hbin = hbin;
    if ( !hbin_contains_offset( hbin, nk->subkeys_off ) ) 
    {
      sub_hbin = lookup_hbin_block( file, nk->subkeys_off );
      if ( !sub_hbin ) 
      {
	/*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing subkey_offset [0x%x]\n", 
	  nk->subkeys_off));*/
	return false;
      }
    }
		
    if (!hbin_prs_lf_records("lf_rec", sub_hbin, depth, nk))
      return false;
  }

  /* get the to the security descriptor.  First look if we have already parsed it */
	
  if ((nk->sk_off!=REGF_OFFSET_NONE) 
      && !(nk->sec_desc = find_sk_record_by_offset( file, nk->sk_off )))
  {
    sub_hbin = hbin;
    if (!hbin_contains_offset(hbin, nk->sk_off))
    {
      sub_hbin = lookup_hbin_block( file, nk->sk_off );
      if ( !sub_hbin ) {
	/*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing sk_offset [0x%x]\n", 
	  nk->subkeys_off));*/
	return false;
      }
    }
		
    if ( !(nk->sec_desc = (REGF_SK_REC*)zalloc(sizeof(REGF_SK_REC) )) )
      return false;
    nk->sec_desc->sk_off = nk->sk_off;
    if ( !hbin_prs_sk_rec( "sk_rec", sub_hbin, depth, nk->sec_desc ))
      return false;
			
    /* add to the list of security descriptors (ref_count has been read from the files) */

    nk->sec_desc->sk_off = nk->sk_off;
    /* XXX: this kind of caching needs to be re-evaluated */
    DLIST_ADD( file->sec_desc_list, nk->sec_desc );
  }
		
  return true;
}
Ejemplo n.º 2
0
/*
 * Connect to a server for getting/setting attributes, possibly on an existing
 * connection.  This works similarly to SMBC_server().
 */
SMBCSRV *
SMBC_attr_server(TALLOC_CTX *ctx,
                 SMBCCTX *context,
                 const char *server,
                 uint16_t port,
                 const char *share,
                 char **pp_workgroup,
                 char **pp_username,
                 char **pp_password)
{
        int flags;
	struct cli_state *ipc_cli = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;
        NTSTATUS nt_status;
	SMBCSRV *srv=NULL;
	SMBCSRV *ipc_srv=NULL;

	/*
	 * Use srv->cli->desthost and srv->cli->share instead of
	 * server and share below to connect to the actual share,
	 * i.e., a normal share or a referred share from
	 * 'msdfs proxy' share.
	 */
	srv = SMBC_server(ctx, context, true, server, port, share,
			pp_workgroup, pp_username, pp_password);
	if (!srv) {
		return NULL;
	}
	server = smbXcli_conn_remote_name(srv->cli->conn);
	share = srv->cli->share;

        /*
         * See if we've already created this special connection.  Reference
         * our "special" share name '*IPC$', which is an impossible real share
         * name due to the leading asterisk.
         */
        ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
                                   pp_workgroup, pp_username, pp_password);
        if (!ipc_srv) {
		int signing_state = SMB_SIGNING_DEFAULT;

                /* We didn't find a cached connection.  Get the password */
		if (!*pp_password || (*pp_password)[0] == '\0') {
                        /* ... then retrieve it now. */
			SMBC_call_auth_fn(ctx, context, server, share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);
			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				return NULL;
			}
                }

                flags = 0;
                if (smbc_getOptionUseKerberos(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
                }
                if (smbc_getOptionUseCCache(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_CCACHE;
                }
		if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
			signing_state = SMB_SIGNING_REQUIRED;
		}

                nt_status = cli_full_connection(&ipc_cli,
						lp_netbios_name(), server,
						NULL, 0, "IPC$", "?????",
						*pp_username,
						*pp_workgroup,
						*pp_password,
						flags,
						signing_state);
                if (! NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("cli_full_connection failed! (%s)\n",
                                 nt_errstr(nt_status)));
                        errno = ENOTSUP;
                        return NULL;
                }

		if (context->internal->smb_encryption_level) {
			/* Attempt encryption. */
			nt_status = cli_cm_force_encryption(ipc_cli,
							    *pp_username,
							    *pp_password,
							    *pp_workgroup,
							    "IPC$");
			if (!NT_STATUS_IS_OK(nt_status)) {

				/*
				 * context->smb_encryption_level ==
				 * 1 means don't fail if encryption can't be
				 * negotiated, == 2 means fail if encryption
				 * can't be negotiated.
				 */

				DEBUG(4,(" SMB encrypt failed on IPC$\n"));

				if (context->internal->smb_encryption_level == 2) {
		                        cli_shutdown(ipc_cli);
					errno = EPERM;
					return NULL;
				}
			}
			DEBUG(4,(" SMB encrypt ok on IPC$\n"));
		}

                ipc_srv = SMB_MALLOC_P(SMBCSRV);
                if (!ipc_srv) {
                        errno = ENOMEM;
                        cli_shutdown(ipc_cli);
                        return NULL;
                }

                ZERO_STRUCTP(ipc_srv);
                DLIST_ADD(ipc_srv->cli, ipc_cli);

                nt_status = cli_rpc_pipe_open_noauth(
			ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1, ("cli_nt_session_open fail!\n"));
                        errno = ENOTSUP;
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                /*
                 * Some systems don't support
                 * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000
                 * so we might as well do it too.
                 */

                nt_status = rpccli_lsa_open_policy(
                        pipe_hnd,
                        talloc_tos(),
                        True,
                        GENERIC_EXECUTE_ACCESS,
                        &ipc_srv->pol);

                if (!NT_STATUS_IS_OK(nt_status)) {
                        errno = SMBC_errno(context, ipc_srv->cli);
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                /* now add it to the cache (internal or external) */

                errno = 0;      /* let cache function set errno if it likes */
                if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv,
                                                             server,
                                                             "*IPC$",
                                                             *pp_workgroup,
                                                             *pp_username)) {
                        DEBUG(3, (" Failed to add server to cache\n"));
                        if (errno == 0) {
                                errno = ENOMEM;
                        }
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                DLIST_ADD(context->internal->servers, ipc_srv);
        }

        return ipc_srv;
}
Ejemplo n.º 3
0
struct tdb_print_db *get_print_db_byname(const char *printername)
{
	struct tdb_print_db *p = NULL, *last_entry = NULL;
	size_t num_open = 0;
	char *printdb_path = NULL;
	bool done_become_root = False;
	char *print_cache_path;
	int ret;

	SMB_ASSERT(printername != NULL);

	for (p = print_db_head, last_entry = print_db_head; p; p = p->next) {
		/* Ensure the list terminates... JRA. */
		SMB_ASSERT(p->next != print_db_head);

		if (p->tdb && strequal(p->printer_name, printername)) {
			DLIST_PROMOTE(print_db_head, p);
			p->ref_count++;
			return p;
		}
		num_open++;
		last_entry = p;
	}

	/* Not found. */
	if (num_open >= MAX_PRINT_DBS_OPEN) {
		/* Try and recycle the last entry. */
		if (print_db_head && last_entry) {
			DLIST_PROMOTE(print_db_head, last_entry);
		}

		for (p = print_db_head; p; p = p->next) {
			if (p->ref_count)
				continue;
			if (p->tdb) {
				if (tdb_close(p->tdb)) {
					DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
								p->printer_name ));
					return NULL;
				}
			}
			p->tdb = NULL;
			p->ref_count = 0;
			memset(p->printer_name, '\0', sizeof(p->printer_name));
			break;
		}
		if (p && print_db_head) {
			DLIST_PROMOTE(print_db_head, p);
			p = print_db_head;
		}
	}

	if (!p)	{
		/* Create one. */
		p = SMB_MALLOC_P(struct tdb_print_db);
		if (!p) {
			DEBUG(0,("get_print_db: malloc fail !\n"));
			return NULL;
		}
		ZERO_STRUCTP(p);
		DLIST_ADD(print_db_head, p);
	}
Ejemplo n.º 4
0
static void add_subnet(struct subnet_record *subrec)
{
	DLIST_ADD(subnetlist, subrec);
}
Ejemplo n.º 5
0
BOOL cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST **pqt_list)
{
	BOOL ret = False;
	uint16 setup;
	char params[16];
	char *rparam=NULL, *rdata=NULL;
	unsigned int rparam_count=0, rdata_count=0;
	unsigned int offset;
	const char *curdata = NULL;
	unsigned int curdata_count = 0;
	TALLOC_CTX *mem_ctx = NULL;
	SMB_NTQUOTA_STRUCT qt;
	SMB_NTQUOTA_LIST *tmp_list_ent;

	if (!cli||!pqt_list)
		smb_panic("cli_list_user_quota() called with NULL Pointer!");

	setup = NT_TRANSACT_GET_USER_QUOTA;

	SSVAL(params, 0,quota_fnum);
	SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
	SIVAL(params, 4,0x00000000);
	SIVAL(params, 8,0x00000000);
	SIVAL(params,12,0x00000000);
	
	if (!cli_send_nt_trans(cli, 
			       NT_TRANSACT_GET_USER_QUOTA, 
			       0, 
			       &setup, 1, 0,
			       params, 16, 4,
			       NULL, 0, 2048)) {
		DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
		goto cleanup;
	}


	if (!cli_receive_nt_trans(cli,
				  &rparam, &rparam_count,
				  &rdata, &rdata_count)) {
		DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
		goto cleanup;
	}

	if (cli_is_error(cli)) {
		ret = False;
		goto cleanup;
	} else {
		ret = True;
	}

	if (rdata_count == 0) {
		*pqt_list = NULL;
		return True;
	}

	if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
		DEBUG(0,("talloc_init() failed\n"));
		return (-1);
	}

	offset = 1;
	for (curdata=rdata,curdata_count=rdata_count;
		((curdata)&&(curdata_count>=8)&&(offset>0));
		curdata +=offset,curdata_count -= offset) {
		ZERO_STRUCT(qt);
		if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
			DEBUG(1,("Failed to parse the quota record\n"));
			goto cleanup;
		}

		if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
			DEBUG(0,("talloc_zero() failed\n"));
			return (-1);
		}

		if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
			DEBUG(0,("talloc_zero() failed\n"));
			return (-1);
		}

		memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
		tmp_list_ent->mem_ctx = mem_ctx;		

		DLIST_ADD((*pqt_list),tmp_list_ent);
	}

	SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);	
	while(1) {
		if (!cli_send_nt_trans(cli, 
				       NT_TRANSACT_GET_USER_QUOTA, 
				       0, 
				       &setup, 1, 0,
				       params, 16, 4,
				       NULL, 0, 2048)) {
			DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
			goto cleanup;
		}
		
		SAFE_FREE(rparam);
		SAFE_FREE(rdata);
		if (!cli_receive_nt_trans(cli,
					  &rparam, &rparam_count,
					  &rdata, &rdata_count)) {
			DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
			goto cleanup;
		}

		if (cli_is_error(cli)) {
			ret = False;
			goto cleanup;
		} else {
			ret = True;
		}
	
		if (rdata_count == 0) {
			break;	
		}

		offset = 1;
		for (curdata=rdata,curdata_count=rdata_count;
			((curdata)&&(curdata_count>=8)&&(offset>0));
			curdata +=offset,curdata_count -= offset) {
			ZERO_STRUCT(qt);
			if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
				DEBUG(1,("Failed to parse the quota record\n"));
				goto cleanup;
			}

			if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
				DEBUG(0,("talloc_zero() failed\n"));
				talloc_destroy(mem_ctx);
				goto cleanup;
			}
	
			if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
				DEBUG(0,("talloc_zero() failed\n"));
				talloc_destroy(mem_ctx);
				goto cleanup;
			}
	
			memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
			tmp_list_ent->mem_ctx = mem_ctx;		
	
			DLIST_ADD((*pqt_list),tmp_list_ent);
		}
	}

 
	ret = True;
 cleanup:
	SAFE_FREE(rparam);
	SAFE_FREE(rdata);
 
	return ret;
}
Ejemplo n.º 6
0
/***************************************************** 
return a connection to a server (existing or new)
*******************************************************/
struct smbw_server *smbw_server(char *server, char *share)
{
	struct smbw_server *srv=NULL;
	struct cli_state c;
	char *username;
	char *password;
	char *workgroup;
	struct nmb_name called, calling;
	char *p, *server_n = server;
	fstring group;
	pstring ipenv;
	struct in_addr ip;

	zero_ip(&ip);
	ZERO_STRUCT(c);

	get_auth_data_fn(server, share, &workgroup, &username, &password);

	/* try to use an existing connection */
	for (srv=smbw_srvs;srv;srv=srv->next) {
		if (strcmp(server,srv->server_name)==0 &&
		    strcmp(share,srv->share_name)==0 &&
		    strcmp(workgroup,srv->workgroup)==0 &&
		    strcmp(username, srv->username) == 0) 
			return srv;
	}

	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}

	make_nmb_name(&calling, global_myname, 0x0);
	make_nmb_name(&called , server, 0x20);

	DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));

	if ((p=strchr(server_n,'#')) && 
	    (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
		struct in_addr sip;
		pstring s;

		fstrcpy(group, server_n);
		p = strchr(group,'#');
		*p = 0;
		
		/* cache the workgroup master lookup */
		slprintf(s,sizeof(s)-1,"MASTER_%s", group);
		if (!(server_n = smbw_getshared(s))) {
			if (!find_master_ip(group, &sip)) {
				errno = ENOENT;
				return NULL;
			}
			fstrcpy(group, inet_ntoa(sip));
			server_n = group;
			smbw_setshared(s,server_n);
		}
	}

	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));

 again:
	slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);

	zero_ip(&ip);
	if ((p=smbw_getshared(ipenv))) {
		ip = *(interpret_addr2(p));
	}

	/* have to open a new connection */
	if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
		errno = ENOENT;
		return NULL;
	}

	if (!cli_session_request(&c, &calling, &called)) {
		cli_shutdown(&c);
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		errno = ENOENT;
		return NULL;
	}

	DEBUG(4,(" session request ok\n"));

	if (!cli_negprot(&c)) {
		cli_shutdown(&c);
		errno = ENOENT;
		return NULL;
	}

	if (!cli_session_setup(&c, username, 
			       password, strlen(password),
			       password, strlen(password),
			       workgroup) &&
	    /* try an anonymous login if it failed */
	    !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
		cli_shutdown(&c);
		errno = EPERM;
		return NULL;
	}

	DEBUG(4,(" session setup ok\n"));

	if (!cli_send_tconX(&c, share, "?????",
			    password, strlen(password)+1)) {
		errno = smbw_errno(&c);
		cli_shutdown(&c);
		return NULL;
	}

	smbw_setshared(ipenv,inet_ntoa(ip));
	
	DEBUG(4,(" tconx ok\n"));

	srv = (struct smbw_server *)malloc(sizeof(*srv));
	if (!srv) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(srv);

	srv->cli = c;

	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));

	srv->server_name = strdup(server);
	if (!srv->server_name) {
		errno = ENOMEM;
		goto failed;
	}

	srv->share_name = strdup(share);
	if (!srv->share_name) {
		errno = ENOMEM;
		goto failed;
	}

	srv->workgroup = strdup(workgroup);
	if (!srv->workgroup) {
		errno = ENOMEM;
		goto failed;
	}

	srv->username = strdup(username);
	if (!srv->username) {
		errno = ENOMEM;
		goto failed;
	}

	/* some programs play with file descriptors fairly intimately. We
	   try to get out of the way by duping to a high fd number */
	if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
		if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == 
		    srv->cli.fd+SMBW_CLI_FD) {
			close(srv->cli.fd);
			srv->cli.fd += SMBW_CLI_FD;
		}
	}

	DLIST_ADD(smbw_srvs, srv);

	return srv;

 failed:
	cli_shutdown(&c);
	if (!srv) return NULL;

	SAFE_FREE(srv->server_name);
	SAFE_FREE(srv->share_name);
	SAFE_FREE(srv);
	return NULL;
}
Ejemplo n.º 7
0
SMBCFILE *
SMBC_open_ctx(SMBCCTX *context,
              const char *fname,
              int flags,
              mode_t mode)
{
	char *server = NULL;
        char *share = NULL;
        char *user = NULL;
        char *password = NULL;
        char *workgroup = NULL;
	char *path = NULL;
	char *targetpath = NULL;
	struct cli_state *targetcli = NULL;
	SMBCSRV *srv   = NULL;
	SMBCFILE *file = NULL;
	uint16_t fd;
	uint16_t port = 0;
	NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID;
	TALLOC_CTX *frame = talloc_stackframe();

	if (!context || !context->internal->initialized) {
		errno = EINVAL;  /* Best I can think of ... */
		TALLOC_FREE(frame);
		return NULL;
	}

	if (!fname) {
		errno = EINVAL;
		TALLOC_FREE(frame);
		return NULL;
	}

	if (SMBC_parse_path(frame,
                            context,
                            fname,
                            &workgroup,
                            &server,
                            &port,
                            &share,
                            &path,
                            &user,
                            &password,
                            NULL)) {
		errno = EINVAL;
		TALLOC_FREE(frame);
		return NULL;
        }

	if (!user || user[0] == (char)0) {
		user = talloc_strdup(frame, smbc_getUser(context));
		if (!user) {
                	errno = ENOMEM;
			TALLOC_FREE(frame);
			return NULL;
		}
	}

	srv = SMBC_server(frame, context, True,
                          server, port, share, &workgroup, &user, &password);
	if (!srv) {
		if (errno == EPERM) errno = EACCES;
		TALLOC_FREE(frame);
		return NULL;  /* SMBC_server sets errno */
	}

	/* Hmmm, the test for a directory is suspect here ... FIXME */

	if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') {
		status = NT_STATUS_OBJECT_PATH_INVALID;
	} else {
		file = SMB_MALLOC_P(SMBCFILE);
		if (!file) {
			errno = ENOMEM;
			TALLOC_FREE(frame);
			return NULL;
		}

		ZERO_STRUCTP(file);

		/*d_printf(">>>open: resolving %s\n", path);*/
		status = cli_resolve_path(
			frame, "", context->internal->auth_info,
			srv->cli, path, &targetcli, &targetpath);
		if (!NT_STATUS_IS_OK(status)) {
			d_printf("Could not resolve %s\n", path);
                        errno = ENOENT;
			SAFE_FREE(file);
			TALLOC_FREE(frame);
			return NULL;
		}
		/*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/

		status = cli_open(targetcli, targetpath, flags,
                                   context->internal->share_mode, &fd);
		if (!NT_STATUS_IS_OK(status)) {

			/* Handle the error ... */

			SAFE_FREE(file);
			errno = SMBC_errno(context, targetcli);
			TALLOC_FREE(frame);
			return NULL;
		}

		/* Fill in file struct */

		file->cli_fd  = fd;
		file->fname   = SMB_STRDUP(fname);
		file->srv     = srv;
		file->offset  = 0;
		file->file    = True;

		DLIST_ADD(context->internal->files, file);

                /*
                 * If the file was opened in O_APPEND mode, all write
                 * operations should be appended to the file.  To do that,
                 * though, using this protocol, would require a getattrE()
                 * call for each and every write, to determine where the end
                 * of the file is. (There does not appear to be an append flag
                 * in the protocol.)  Rather than add all of that overhead of
                 * retrieving the current end-of-file offset prior to each
                 * write operation, we'll assume that most append operations
                 * will continuously write, so we'll just set the offset to
                 * the end of the file now and hope that's adequate.
                 *
                 * Note to self: If this proves inadequate, and O_APPEND
                 * should, in some cases, be forced for each write, add a
                 * field in the context options structure, for
                 * "strict_append_mode" which would select between the current
                 * behavior (if FALSE) or issuing a getattrE() prior to each
                 * write and forcing the write to the end of the file (if
                 * TRUE).  Adding that capability will likely require adding
                 * an "append" flag into the _SMBCFILE structure to track
                 * whether a file was opened in O_APPEND mode.  -- djl
                 */
                if (flags & O_APPEND) {
                        if (SMBC_lseek_ctx(context, file, 0, SEEK_END) < 0) {
                                (void) SMBC_close_ctx(context, file);
                                errno = ENXIO;
				TALLOC_FREE(frame);
                                return NULL;
                        }
                }

		TALLOC_FREE(frame);
		return file;
	}

	/* Check if opendir needed ... */

	if (!NT_STATUS_IS_OK(status)) {
		int eno = 0;

		eno = SMBC_errno(context, srv->cli);
		file = smbc_getFunctionOpendir(context)(context, fname);
		if (!file) errno = eno;
		TALLOC_FREE(frame);
		return file;
	}

	errno = EINVAL; /* FIXME, correct errno ? */
	TALLOC_FREE(frame);
	return NULL;
}
Ejemplo n.º 8
0
NTSTATUS add_ccache_to_list(const char *princ_name,
			    const char *ccname,
			    const char *service,
			    const char *username,
			    const char *pass,
			    const char *realm,
			    uid_t uid,
			    time_t create_time,
			    time_t ticket_end,
			    time_t renew_until,
			    bool postponed_request)
{
	struct WINBINDD_CCACHE_ENTRY *entry = NULL;
	struct timeval t;
	NTSTATUS ntret;
#ifdef HAVE_KRB5
	int ret;
#endif

	if ((username == NULL && princ_name == NULL) ||
	    ccname == NULL || uid < 0) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (ccache_entry_count() + 1 > MAX_CCACHES) {
		DEBUG(10,("add_ccache_to_list: "
			"max number of ccaches reached\n"));
		return NT_STATUS_NO_MORE_ENTRIES;
	}

	/* If it is cached login, destroy krb5 ticket
	 * to avoid surprise. */
#ifdef HAVE_KRB5
	if (postponed_request) {
		/* ignore KRB5_FCC_NOFILE error here */
		ret = ads_kdestroy(ccname);
		if (ret == KRB5_FCC_NOFILE) {
			ret = 0;
		}
		if (ret) {
			DEBUG(0, ("add_ccache_to_list: failed to destroy "
				   "user krb5 ccache %s with %s\n", ccname,
				   error_message(ret)));
			return krb5_to_nt_status(ret);
		}
		DEBUG(10, ("add_ccache_to_list: successfully destroyed "
			   "krb5 ccache %s for user %s\n", ccname,
			   username));
	}
#endif

	/* Reference count old entries */
	entry = get_ccache_by_username(username);
	if (entry) {
		/* Check cached entries are identical. */
		if (!ccache_entry_identical(username, uid, ccname)) {
			return NT_STATUS_INVALID_PARAMETER;
		}
		entry->ref_count++;
		DEBUG(10,("add_ccache_to_list: "
			"ref count on entry %s is now %d\n",
			username, entry->ref_count));
		/* FIXME: in this case we still might want to have a krb5 cred
		 * event handler created - gd
		 * Add ticket refresh handler here */

		if (!lp_winbind_refresh_tickets() || renew_until <= 0) {
			return NT_STATUS_OK;
		}

		if (!entry->event) {
			if (postponed_request) {
				t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
				add_krb5_ticket_gain_handler_event(entry, t);
			} else {
				/* Renew at 1/2 the ticket expiration time */
#if defined(DEBUG_KRB5_TKT_RENEWAL)
				t = timeval_set(time(NULL)+30, 0);
#else
				t = timeval_set(krb5_event_refresh_time(ticket_end),
						0);
#endif
				if (!entry->refresh_time) {
					entry->refresh_time = t.tv_sec;
				}
				entry->event = tevent_add_timer(winbind_event_context(),
							       entry,
							       t,
							       krb5_ticket_refresh_handler,
							       entry);
			}

			if (!entry->event) {
				ntret = remove_ccache(username);
				if (!NT_STATUS_IS_OK(ntret)) {
					DEBUG(0, ("add_ccache_to_list: Failed to remove krb5 "
						  "ccache %s for user %s\n", entry->ccname,
						  entry->username));
					DEBUG(0, ("add_ccache_to_list: error is %s\n",
						  nt_errstr(ntret)));
					return ntret;
				}
				return NT_STATUS_NO_MEMORY;
			}

			DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n"));

		}

		/*
		 * If we're set up to renew our krb5 tickets, we must
		 * cache the credentials in memory for the ticket
		 * renew function (or increase the reference count
		 * if we're logging in more than once). Fix inspired
		 * by patch from Ian Gordon <*****@*****.**>
		 * for bugid #9098.
		 */

		ntret = winbindd_add_memory_creds(username, uid, pass);
		DEBUG(10, ("winbindd_add_memory_creds returned: %s\n",
			nt_errstr(ntret)));

		return NT_STATUS_OK;
	}

	entry = talloc(NULL, struct WINBINDD_CCACHE_ENTRY);
	if (!entry) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCTP(entry);

	if (username) {
		entry->username = talloc_strdup(entry, username);
		if (!entry->username) {
			goto no_mem;
		}
	}
	if (princ_name) {
		entry->principal_name = talloc_strdup(entry, princ_name);
		if (!entry->principal_name) {
			goto no_mem;
		}
	}
	if (service) {
		entry->service = talloc_strdup(entry, service);
		if (!entry->service) {
			goto no_mem;
		}
	}

	entry->ccname = talloc_strdup(entry, ccname);
	if (!entry->ccname) {
		goto no_mem;
	}

	entry->realm = talloc_strdup(entry, realm);
	if (!entry->realm) {
		goto no_mem;
	}

	entry->create_time = create_time;
	entry->renew_until = renew_until;
	entry->uid = uid;
	entry->ref_count = 1;

	if (!lp_winbind_refresh_tickets() || renew_until <= 0) {
		goto add_entry;
	}

	if (postponed_request) {
		t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
		add_krb5_ticket_gain_handler_event(entry, t);
	} else {
		/* Renew at 1/2 the ticket expiration time */
#if defined(DEBUG_KRB5_TKT_RENEWAL)
		t = timeval_set(time(NULL)+30, 0);
#else
		t = timeval_set(krb5_event_refresh_time(ticket_end), 0);
#endif
		if (entry->refresh_time == 0) {
			entry->refresh_time = t.tv_sec;
		}
		entry->event = tevent_add_timer(winbind_event_context(),
					       entry,
					       t,
					       krb5_ticket_refresh_handler,
					       entry);
	}

	if (!entry->event) {
		goto no_mem;
	}

	DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n"));

 add_entry:

	DLIST_ADD(ccache_list, entry);

	DEBUG(10,("add_ccache_to_list: "
		"added ccache [%s] for user [%s] to the list\n",
		ccname, username));

	if (entry->event) {
		/*
		 * If we're set up to renew our krb5 tickets, we must
		 * cache the credentials in memory for the ticket
		 * renew function. Fix inspired by patch from
		 * Ian Gordon <*****@*****.**> for
		 * bugid #9098.
		 */

		ntret = winbindd_add_memory_creds(username, uid, pass);
		DEBUG(10, ("winbindd_add_memory_creds returned: %s\n",
			nt_errstr(ntret)));
	}

	return NT_STATUS_OK;

 no_mem:

	TALLOC_FREE(entry);
	return NT_STATUS_NO_MEMORY;
}
Ejemplo n.º 9
0
static NTSTATUS winbindd_add_memory_creds_internal(const char *username,
						   uid_t uid,
						   const char *pass)
{
	/* Shortcut to ensure we don't store if no mlock. */
#if !defined(HAVE_MLOCK) || !defined(HAVE_MUNLOCK)
	return NT_STATUS_OK;
#else
	NTSTATUS status;
	struct WINBINDD_MEMORY_CREDS *memcredp = NULL;

	memcredp = find_memory_creds_by_name(username);
	if (uid == (uid_t)-1) {
		DEBUG(0,("winbindd_add_memory_creds_internal: "
			"invalid uid for user %s.\n", username));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (memcredp) {
		/* Already exists. Increment the reference count and replace stored creds. */
		if (uid != memcredp->uid) {
			DEBUG(0,("winbindd_add_memory_creds_internal: "
				"uid %u for user %s doesn't "
				"match stored uid %u. Replacing.\n",
				(unsigned int)uid, username,
				(unsigned int)memcredp->uid));
			memcredp->uid = uid;
		}
		memcredp->ref_count++;
		DEBUG(10,("winbindd_add_memory_creds_internal: "
			"ref count for user %s is now %d\n",
			username, memcredp->ref_count));
		return winbindd_replace_memory_creds_internal(memcredp, pass);
	}

	memcredp = talloc_zero(NULL, struct WINBINDD_MEMORY_CREDS);
	if (!memcredp) {
		return NT_STATUS_NO_MEMORY;
	}
	memcredp->username = talloc_strdup(memcredp, username);
	if (!memcredp->username) {
		talloc_destroy(memcredp);
		return NT_STATUS_NO_MEMORY;
	}

	status = store_memory_creds(memcredp, pass);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_destroy(memcredp);
		return status;
	}

	memcredp->uid = uid;
	memcredp->ref_count = 1;
	DLIST_ADD(memory_creds_list, memcredp);

	DEBUG(10,("winbindd_add_memory_creds_internal: "
		"added entry for user %s\n", username));

	return NT_STATUS_OK;
#endif
}
Ejemplo n.º 10
0
pipes_struct *open_rpc_pipe_p(char *pipe_name, 
			      connection_struct *conn, uint16 vuid)
{
	int i;
	pipes_struct *p;
	static int next_pipe;

	DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
		 pipe_name, pipes_open));
	
	/* not repeating pipe numbers makes it easier to track things in 
	   log files and prevents client bugs where pipe numbers are reused
	   over connection restarts */
	if (next_pipe == 0)
		next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES;

	i = bitmap_find(bmap, next_pipe);

	if (i == -1) {
		DEBUG(0,("ERROR! Out of pipe structures\n"));
		return NULL;
	}

	next_pipe = (i+1) % MAX_OPEN_PIPES;

	for (p = Pipes; p; p = p->next)
		DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  

	p = (pipes_struct *)malloc(sizeof(*p));

	if (!p)
		return NULL;

	ZERO_STRUCTP(p);

	DLIST_ADD(Pipes, p);

	/*
	 * Initialize the incoming RPC data buffer with one PDU worth of memory.
	 * We cheat here and say we're marshalling, as we intend to add incoming
	 * data directly into the prs_struct and we want it to auto grow. We will
	 * change the type to UNMARSALLING before processing the stream.
	 */

	if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, 4, MARSHALL)) {
		DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
		return NULL;
	}

	bitmap_set(bmap, i);
	i += pipe_handle_offset;

	pipes_open++;

	p->pnum = i;

	p->open = True;
	p->device_state = 0;
	p->priority = 0;
	p->conn = conn;
	p->vuid  = vuid;

	p->max_trans_reply = 0;
	
	p->ntlmssp_chal_flags = 0;
	p->ntlmssp_auth_validated = False;
	p->ntlmssp_auth_requested = False;

	p->pipe_bound = False;
	p->fault_state = False;

	/*
	 * Initialize the incoming RPC struct.
	 */

	p->in_data.pdu_needed_len = 0;
	p->in_data.pdu_received_len = 0;

	/*
	 * Initialize the outgoing RPC struct.
	 */

	p->out_data.current_pdu_len = 0;
	p->out_data.current_pdu_sent = 0;
	p->out_data.data_sent_length = 0;

	/*
	 * Initialize the outgoing RPC data buffer with no memory.
	 */	
	prs_init(&p->out_data.rdata, 0, 4, MARSHALL);
	
	p->uid = (uid_t)-1;
	p->gid = (gid_t)-1;
	
	fstrcpy(p->name, pipe_name);
	
	DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
		 pipe_name, i, pipes_open));
	
	chain_p = p;
	
	/* OVERWRITE p as a temp variable, to display all open pipes */ 
	for (p = Pipes; p; p = p->next)
		DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum));  

	return chain_p;
}
Ejemplo n.º 11
0
static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
					struct smbXsrv_session_auth0 **_auth,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					struct auth_session_info *session_info,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	NTSTATUS status;
	bool guest = false;
	uint8_t session_key[16];
	struct smbXsrv_session *x = session;
	struct smbXsrv_session_auth0 *auth = *_auth;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	size_t i;
	struct _derivation {
		DATA_BLOB label;
		DATA_BLOB context;
	};
	struct {
		struct _derivation signing;
		struct _derivation encryption;
		struct _derivation decryption;
		struct _derivation application;
	} derivation = { };

	*_auth = NULL;

	if (xconn->protocol >= PROTOCOL_SMB3_10) {
		struct smbXsrv_preauth *preauth;
		struct _derivation *d;
		DATA_BLOB p;
		struct hc_sha512state sctx;

		preauth = talloc_move(smb2req, &auth->preauth);

		samba_SHA512_Init(&sctx);
		samba_SHA512_Update(&sctx, preauth->sha512_value,
				    sizeof(preauth->sha512_value));
		for (i = 1; i < smb2req->in.vector_count; i++) {
			samba_SHA512_Update(&sctx,
					    smb2req->in.vector[i].iov_base,
					    smb2req->in.vector[i].iov_len);
		}
		samba_SHA512_Final(preauth->sha512_value, &sctx);

		p = data_blob_const(preauth->sha512_value,
				    sizeof(preauth->sha512_value));

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMBSigningKey");
		d->context = p;

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMBC2SCipherKey");
		d->context = p;

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMBS2CCipherKey");
		d->context = p;

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMBAppKey");
		d->context = p;

	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d;

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMB2AESCMAC");
		d->context = data_blob_string_const_null("SmbSign");

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerIn ");

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerOut");

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMB2APP");
		d->context = data_blob_string_const_null("SmbRpc");
	}

	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
		x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
	}

	if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
	    (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
		x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
	}

	if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
		x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
			SMBXSRV_ENCRYPTION_DESIRED;
	}

	if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
		/* we map anonymous to guest internally */
		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
		/* force no signing */
		x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
		guest = true;
	}

	if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
		DEBUG(1,("reject guest session as encryption is required\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (xconn->smb2.server.cipher == 0) {
		if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
			DEBUG(1,("reject session with dialect[0x%04X] "
				 "as encryption is required\n",
				 xconn->smb2.server.dialect));
			return NT_STATUS_ACCESS_DENIED;
		}
	} else {
		x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
	}

	if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
		*out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	x->global->signing_key = data_blob_talloc(x->global,
						  session_key,
						  sizeof(session_key));
	if (x->global->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.signing;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->signing_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.decryption;

		x->global->decryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->decryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->decryption_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.encryption;
		size_t nonce_size;

		x->global->encryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->encryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->encryption_key.data);

		/*
		 * CCM and GCM algorithms must never have their
		 * nonce wrap, or the security of the whole
		 * communication and the keys is destroyed.
		 * We must drop the connection once we have
		 * transfered too much data.
		 *
		 * NOTE: We assume nonces greater than 8 bytes.
		 */
		generate_random_buffer((uint8_t *)&x->nonce_high_random,
				       sizeof(x->nonce_high_random));
		switch (xconn->smb2.server.cipher) {
		case SMB2_ENCRYPTION_AES128_CCM:
			nonce_size = AES_CCM_128_NONCE_SIZE;
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			nonce_size = AES_GCM_128_IV_SIZE;
			break;
		default:
			nonce_size = 0;
			break;
		}
		x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
		x->nonce_high = 0;
		x->nonce_low = 0;
	}

	x->global->application_key = data_blob_dup_talloc(x->global,
						x->global->signing_key);
	if (x->global->application_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.application;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->application_key.data);
	}
	ZERO_STRUCT(session_key);

	x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
						x->global->signing_key);
	if (x->global->channels[0].signing_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_clear_free(&session_info->session_key);
	session_info->session_key = data_blob_dup_talloc(session_info,
						x->global->application_key);
	if (session_info->session_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	session->compat = talloc_zero(session, struct user_struct);
	if (session->compat == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	session->compat->session = session;
	session->compat->homes_snum = -1;
	session->compat->session_info = session_info;
	session->compat->session_keystr = NULL;
	session->compat->vuid = session->global->session_wire_id;
	DLIST_ADD(smb2req->sconn->users, session->compat);
	smb2req->sconn->num_users++;

	if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
		session->compat->homes_snum =
			register_homes_share(session_info->unix_info->unix_name);
	}

	set_current_user_info(session_info->unix_info->sanitized_username,
			      session_info->unix_info->unix_name,
			      session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;
	session->global->auth_session_info = talloc_move(session->global,
							 &session_info);
	session->global->auth_session_info_seqnum += 1;
	for (i=0; i < session->global->num_channels; i++) {
		struct smbXsrv_channel_global0 *_c =
			&session->global->channels[i];

		_c->auth_session_info_seqnum =
			session->global->auth_session_info_seqnum;
	}
	session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
	session->global->expiration_time = gensec_expire_time(auth->gensec);

	if (!session_claim(session)) {
		DEBUG(1, ("smb2: Failed to claim session "
			"for vuid=%llu\n",
			(unsigned long long)session->compat->vuid));
		return NT_STATUS_LOGON_FAILURE;
	}

	TALLOC_FREE(auth);
	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	/*
	 * we attach the session to the request
	 * so that the response can be signed
	 */
	if (!guest) {
		smb2req->do_signing = true;
	}

	global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
Ejemplo n.º 12
0
int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name)
{
	user_struct *vuser = NULL;

	/* Ensure no vuid gets registered in share level security. */
	if(lp_security() == SEC_SHARE) {
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	/* Limit allowed vuids to 16bits - VUID_OFFSET. */
	if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	if((vuser = SMB_MALLOC_P(user_struct)) == NULL) {
		DEBUG(0,("Failed to malloc users struct!\n"));
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	ZERO_STRUCTP(vuser);

	/* Allocate a free vuid. Yes this is a linear search... :-) */
	while( get_valid_user_struct(next_vuid) != NULL ) {
		next_vuid++;
		/* Check for vuid wrap. */
		if (next_vuid == UID_FIELD_INVALID)
			next_vuid = VUID_OFFSET;
	}

	DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));

	vuser->vuid = next_vuid;

	/* the next functions should be done by a SID mapping system (SMS) as
	 * the new real sam db won't have reference to unix uids or gids
	 */
	
	vuser->uid = server_info->uid;
	vuser->gid = server_info->gid;
	
	vuser->n_groups = server_info->n_groups;
	if (vuser->n_groups) {
		if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
			DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
			data_blob_free(&session_key);
			free(vuser);
			free_server_info(&server_info);
			return UID_FIELD_INVALID;
		}
	}

	vuser->guest = server_info->guest;
	fstrcpy(vuser->user.unix_name, server_info->unix_name); 

	/* This is a potentially untrusted username */
	alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));

	fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
	fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));

	{
		/* Keep the homedir handy */
		const char *homedir = pdb_get_homedir(server_info->sam_account);
		const char *logon_script = pdb_get_logon_script(server_info->sam_account);

		if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) {
			const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
			if (unix_homedir) {
				vuser->unix_homedir = smb_xstrdup(unix_homedir);
			}
		} else {
			struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name);
			if (passwd) {
				vuser->unix_homedir = smb_xstrdup(passwd->pw_dir);
				passwd_free(&passwd);
			}
		}
		
		if (homedir) {
			vuser->homedir = smb_xstrdup(homedir);
		}
		if (logon_script) {
			vuser->logon_script = smb_xstrdup(logon_script);
		}
	}

	vuser->session_key = session_key;

	DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", 
		  (unsigned int)vuser->uid, 
		  (unsigned int)vuser->gid,
		  vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest ));

	DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));	

 	if (server_info->ptok) {
		vuser->nt_user_token = dup_nt_token(server_info->ptok);
	} else {
		DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
		free_server_info(&server_info);
		data_blob_free(&session_key);
		SAFE_FREE(vuser->homedir);
		SAFE_FREE(vuser->unix_homedir);
		SAFE_FREE(vuser->logon_script);

		SAFE_FREE(vuser);
		return UID_FIELD_INVALID;
	}

	/* use this to keep tabs on all our info from the authentication */
	vuser->server_info = server_info;

	DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));

	next_vuid++;
	num_validated_vuids++;

	DLIST_ADD(validated_users, vuser);

	if (!session_claim(vuser)) {
		DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));
		invalidate_vuid(vuser->vuid);
		return -1;
	}

	/* Register a home dir service for this user iff
	
	   (a) This is not a guest connection,
	   (b) we have a home directory defined 
	   (c) there s not an existing static share by that name
	   
	   If a share exists by this name (autoloaded or not) reuse it . */

	vuser->homes_snum = -1;

	if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) 
	{
		int servicenumber = lp_servicenumber(vuser->user.unix_name);

		if ( servicenumber == -1 ) {
			DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", 
				vuser->user.unix_name, vuser->unix_homedir));
			vuser->homes_snum = add_home_service(vuser->user.unix_name, 
						vuser->user.unix_name, vuser->unix_homedir);
		} else {
			DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", 
				vuser->user.unix_name, lp_pathname(servicenumber) ));
			vuser->homes_snum = servicenumber;
		}
	} 
	
	if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) {
		/* Try and turn on server signing on the first non-guest sessionsetup. */
		srv_set_signing(vuser->session_key, response_blob);
	}
	
	/* fill in the current_user_info struct */
	set_current_user_info( &vuser->user );


	return vuser->vuid;
}
Ejemplo n.º 13
0
static NTSTATUS smbd_smb2_auth_generic_return(struct smbd_smb2_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					DATA_BLOB in_security_buffer,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	bool guest = false;

	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
		session->do_signing = true;
	}

	if (security_session_user_level(session->session_info, NULL) < SECURITY_USER) {
		/* we map anonymous to guest internally */
		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
		/* force no signing */
		session->do_signing = false;
		guest = true;
	}

	session->session_key = session->session_info->session_key;

	session->compat_vuser = talloc_zero(session, user_struct);
	if (session->compat_vuser == NULL) {
		TALLOC_FREE(session);
		return NT_STATUS_NO_MEMORY;
	}
	session->compat_vuser->gensec_security = session->gensec_security;
	session->compat_vuser->homes_snum = -1;
	session->compat_vuser->session_info = session->session_info;
	session->compat_vuser->session_keystr = NULL;
	session->compat_vuser->vuid = session->vuid;
	DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);

	if (security_session_user_level(session->session_info, NULL) >= SECURITY_USER) {
		session->compat_vuser->homes_snum =
			register_homes_share(session->session_info->unix_info->unix_name);
	}

	if (!session_claim(session->sconn, session->compat_vuser)) {
		DEBUG(1, ("smb2: Failed to claim session "
			"for vuid=%d\n",
			session->compat_vuser->vuid));
		TALLOC_FREE(session);
		return NT_STATUS_LOGON_FAILURE;
	}

	set_current_user_info(session->session_info->unix_info->sanitized_username,
			      session->session_info->unix_info->unix_name,
			      session->session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;

	/*
	 * we attach the session to the request
	 * so that the response can be signed
	 */
	smb2req->session = session;
	if (!guest) {
		smb2req->do_signing = true;
	}

	global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);

	*out_session_id = session->vuid;

	return NT_STATUS_OK;
}
Ejemplo n.º 14
0
NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
		  files_struct **result)
{
	struct smbd_server_connection *sconn = conn->sconn;
	int i;
	files_struct *fsp;
	NTSTATUS status;

	/* we want to give out file handles differently on each new
	   connection because of a common bug in MS clients where they try to
	   reuse a file descriptor from an earlier smb connection. This code
	   increases the chance that the errant client will get an error rather
	   than causing corruption */
	if (sconn->first_file == 0) {
		sconn->first_file = (getpid() ^ (int)time(NULL));
		sconn->first_file %= sconn->real_max_open_files;
	}

	/* TODO: Port the id-tree implementation from Samba4 */

	i = bitmap_find(sconn->file_bmap, sconn->first_file);
	if (i == -1) {
		DEBUG(0,("ERROR! Out of file structures\n"));
		/* TODO: We have to unconditionally return a DOS error here,
		 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
		 * NTSTATUS negotiated */
		return NT_STATUS_TOO_MANY_OPENED_FILES;
	}

	/*
	 * Make a child of the connection_struct as an fsp can't exist
	 * independent of a connection.
	 */
	fsp = talloc_zero(conn, struct files_struct);
	if (!fsp) {
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * This can't be a child of fsp because the file_handle can be ref'd
	 * when doing a dos/fcb open, which will then share the file_handle
	 * across multiple fsps.
	 */
	fsp->fh = talloc_zero(conn, struct fd_handle);
	if (!fsp->fh) {
		TALLOC_FREE(fsp);
		return NT_STATUS_NO_MEMORY;
	}

	fsp->fh->ref_count = 1;
	fsp->fh->fd = -1;

	fsp->conn = conn;
	fsp->fh->gen_id = get_gen_count(sconn);
	GetTimeOfDay(&fsp->open_time);

	sconn->first_file = (i+1) % (sconn->real_max_open_files);

	bitmap_set(sconn->file_bmap, i);

	fsp->fnum = i + FILE_HANDLE_OFFSET;
	SMB_ASSERT(fsp->fnum < 65536);

	/*
	 * Create an smb_filename with "" for the base_name.  There are very
	 * few NULL checks, so make sure it's initialized with something. to
	 * be safe until an audit can be done.
	 */
	status = create_synthetic_smb_fname(fsp, "", NULL, NULL,
					    &fsp->fsp_name);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(fsp);
		TALLOC_FREE(fsp->fh);
	}

	DLIST_ADD(sconn->files, fsp);
	sconn->num_files += 1;

	DEBUG(5,("allocated file structure %d, fnum = %d (%u used)\n",
		 i, fsp->fnum, (unsigned int)sconn->num_files));

	if (req != NULL) {
		req->chain_fsp = fsp;
	}

	/* A new fsp invalidates the positive and
	  negative fsp_fi_cache as the new fsp is pushed
	  at the start of the list and we search from
	  a cache hit to the *end* of the list. */

	ZERO_STRUCT(sconn->fsp_fi_cache);

	conn->num_files_open++;

	*result = fsp;
	return NT_STATUS_OK;
}
Ejemplo n.º 15
0
WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
			       struct dsdb_schema *schema,
			       struct ldb_message *msg)
{
	WERROR status;
	struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute);
	if (!attr) {
		return WERR_NOMEM;
	}

	GET_STRING_LDB(msg, "cn", attr, attr, cn, false);
	GET_STRING_LDB(msg, "lDAPDisplayName", attr, attr, lDAPDisplayName, true);
	GET_STRING_LDB(msg, "attributeID", attr, attr, attributeID_oid, true);
	if (!schema->prefixmap || schema->prefixmap->length == 0) {
		/* set an invalid value */
		attr->attributeID_id = DRSUAPI_ATTID_INVALID;
	} else {
		status = dsdb_schema_pfm_make_attid(schema->prefixmap,
						    attr->attributeID_oid,
						    &attr->attributeID_id);
		if (!W_ERROR_IS_OK(status)) {
			DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
				__location__, attr->lDAPDisplayName, attr->attributeID_oid,
				win_errstr(status)));
			return status;
		}
	}
	/* fetch msDS-IntId to be used in resolving ATTRTYP values */
	GET_UINT32_LDB(msg, "msDS-IntId", attr, msDS_IntId);

	GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
	GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);

	GET_GUID_LDB(msg, "attributeSecurityGUID", attr, attributeSecurityGUID);

	GET_GUID_LDB(msg, "objectGUID", attr, objectGUID);

	GET_UINT32_LDB(msg, "searchFlags", attr, searchFlags);
	GET_UINT32_LDB(msg, "systemFlags", attr, systemFlags);
	GET_BOOL_LDB(msg, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
	GET_UINT32_LDB(msg, "linkID", attr, linkID);

	GET_STRING_LDB(msg, "attributeSyntax", attr, attr, attributeSyntax_oid, true);
	if (!schema->prefixmap || schema->prefixmap->length == 0) {
		/* set an invalid value */
		attr->attributeSyntax_id = DRSUAPI_ATTID_INVALID;
	} else {
		status = dsdb_schema_pfm_attid_from_oid(schema->prefixmap,
							attr->attributeSyntax_oid,
							&attr->attributeSyntax_id);
		if (!W_ERROR_IS_OK(status)) {
			DEBUG(0,("%s: '%s': unable to map attributeSyntax_ %s: %s\n",
				__location__, attr->lDAPDisplayName, attr->attributeSyntax_oid,
				win_errstr(status)));
			return status;
		}
	}
	GET_UINT32_LDB(msg, "oMSyntax", attr, oMSyntax);
	GET_BLOB_LDB(msg, "oMObjectClass", attr, attr, oMObjectClass);

	GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
	GET_UINT32_PTR_LDB(msg, "rangeLower", attr, attr, rangeLower);
	GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, attr, rangeUpper);
	GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);

	GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
	GET_BLOB_LDB(msg, "msDs-Schema-Extensions", attr, attr, msDs_Schema_Extensions);

	GET_BOOL_LDB(msg, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
	GET_STRING_LDB(msg, "adminDisplayName", attr, attr, adminDisplayName, false);
	GET_STRING_LDB(msg, "adminDescription", attr, attr, adminDescription, false);
	GET_STRING_LDB(msg, "classDisplayName", attr, attr, classDisplayName, false);
	GET_BOOL_LDB(msg, "isEphemeral", attr, isEphemeral, false);
	GET_BOOL_LDB(msg, "isDefunct", attr, isDefunct, false);
	GET_BOOL_LDB(msg, "systemOnly", attr, systemOnly, false);

	attr->syntax = dsdb_syntax_for_attribute(attr);
	if (!attr->syntax) {
		DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
			 attr->lDAPDisplayName));
		return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
	}

	if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Unknown schema syntax for %s - ldb_syntax: %s, ldap_oid: %s\n",
			 attr->lDAPDisplayName,
			 attr->syntax->ldb_syntax,
			 attr->syntax->ldap_oid));
		return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
	}

	DLIST_ADD(schema->attributes, attr);
	return WERR_OK;
}
Ejemplo n.º 16
0
NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
		  files_struct **result)
{
	int i;
	files_struct *fsp;

	/* we want to give out file handles differently on each new
	   connection because of a common bug in MS clients where they try to
	   reuse a file descriptor from an earlier smb connection. This code
	   increases the chance that the errant client will get an error rather
	   than causing corruption */
	if (first_file == 0) {
		first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
	}

	/* TODO: Port the id-tree implementation from Samba4 */

	i = bitmap_find(file_bmap, first_file);
	if (i == -1) {
		DEBUG(0,("ERROR! Out of file structures\n"));
		/* TODO: We have to unconditionally return a DOS error here,
		 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
		 * NTSTATUS negotiated */
		return NT_STATUS_TOO_MANY_OPENED_FILES;
	}

	fsp = SMB_MALLOC_P(files_struct);
	if (!fsp) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCTP(fsp);

	fsp->fh = SMB_MALLOC_P(struct fd_handle);
	if (!fsp->fh) {
		SAFE_FREE(fsp);
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCTP(fsp->fh);

	fsp->fh->ref_count = 1;
	fsp->fh->fd = -1;

	fsp->conn = conn;
	fsp->fh->gen_id = get_gen_count();
	GetTimeOfDay(&fsp->open_time);

	first_file = (i+1) % real_max_open_files;

	bitmap_set(file_bmap, i);
	files_used++;

	fsp->fnum = i + FILE_HANDLE_OFFSET;
	SMB_ASSERT(fsp->fnum < 65536);

	string_set(&fsp->fsp_name,"");
	
	DLIST_ADD(Files, fsp);

	DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
		 i, fsp->fnum, files_used));

	if (req != NULL) {
		req->chain_fsp = fsp;
	}

	/* A new fsp invalidates the positive and
	  negative fsp_fi_cache as the new fsp is pushed
	  at the start of the list and we search from
	  a cache hit to the *end* of the list. */

	ZERO_STRUCT(fsp_fi_cache);

	conn->num_files_open++;

	*result = fsp;
	return NT_STATUS_OK;
}
Ejemplo n.º 17
0
WERROR dsdb_class_from_ldb(struct dsdb_schema *schema,
			   struct ldb_message *msg)
{
	WERROR status;
	struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class);
	if (!obj) {
		return WERR_NOMEM;
	}
	GET_STRING_LDB(msg, "cn", obj, obj, cn, false);
	GET_STRING_LDB(msg, "lDAPDisplayName", obj, obj, lDAPDisplayName, true);
	GET_STRING_LDB(msg, "governsID", obj, obj, governsID_oid, true);
	if (!schema->prefixmap || schema->prefixmap->length == 0) {
		/* set an invalid value */
		obj->governsID_id = DRSUAPI_ATTID_INVALID;
	} else {
		status = dsdb_schema_pfm_make_attid(schema->prefixmap,
						    obj->governsID_oid,
						    &obj->governsID_id);
		if (!W_ERROR_IS_OK(status)) {
			DEBUG(0,("%s: '%s': unable to map governsID %s: %s\n",
				__location__, obj->lDAPDisplayName, obj->governsID_oid,
				win_errstr(status)));
			return status;
		}
	}
	GET_GUID_LDB(msg, "schemaIDGUID", obj, schemaIDGUID);
	GET_GUID_LDB(msg, "objectGUID", obj, objectGUID);

	GET_UINT32_LDB(msg, "objectClassCategory", obj, objectClassCategory);
	GET_STRING_LDB(msg, "rDNAttID", obj, obj, rDNAttID, false);
	GET_STRING_LDB(msg, "defaultObjectCategory", obj, obj, defaultObjectCategory, true);
 
	GET_STRING_LDB(msg, "subClassOf", obj, obj, subClassOf, true);

	GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", obj, obj, systemAuxiliaryClass);
	GET_STRING_LIST_LDB(msg, "auxiliaryClass", obj, obj, auxiliaryClass);

	GET_STRING_LIST_LDB(msg, "systemMustContain", obj, obj, systemMustContain);
	GET_STRING_LIST_LDB(msg, "systemMayContain", obj, obj, systemMayContain);
	GET_STRING_LIST_LDB(msg, "mustContain", obj, obj, mustContain);
	GET_STRING_LIST_LDB(msg, "mayContain", obj, obj, mayContain);

	GET_STRING_LIST_LDB(msg, "systemPossSuperiors", obj, obj, systemPossSuperiors);
	GET_STRING_LIST_LDB(msg, "possSuperiors", obj, obj, possSuperiors);

	GET_STRING_LDB(msg, "defaultSecurityDescriptor", obj, obj, defaultSecurityDescriptor, false);

	GET_UINT32_LDB(msg, "schemaFlagsEx", obj, schemaFlagsEx);
	GET_UINT32_LDB(msg, "systemFlags", obj, systemFlags);
	GET_BLOB_LDB(msg, "msDs-Schema-Extensions", obj, obj, msDs_Schema_Extensions);

	GET_BOOL_LDB(msg, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
	GET_STRING_LDB(msg, "adminDisplayName", obj, obj, adminDisplayName, false);
	GET_STRING_LDB(msg, "adminDescription", obj, obj, adminDescription, false);
	GET_STRING_LDB(msg, "classDisplayName", obj, obj, classDisplayName, false);
	GET_BOOL_LDB(msg, "defaultHidingValue", obj, defaultHidingValue, false);
	GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
	GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);

	DLIST_ADD(schema->classes, obj);
	return WERR_OK;
}
Ejemplo n.º 18
0
static void add_workgroup(struct subnet_record *subrec, struct work_record *work)
{
	work->subnet = subrec;
	DLIST_ADD(subrec->workgrouplist, work);
	subrec->work_changed = True;
}
Ejemplo n.º 19
0
/***************************************************** 
a wrapper for open()
*******************************************************/
int smbw_open(const char *fname, int flags, mode_t mode)
{
	fstring server, share;
	pstring path;
	struct smbw_server *srv=NULL;
	int eno=0, fd = -1;
	struct smbw_file *file=NULL;

	smbw_init();

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_busy++;	

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (path[strlen(path)-1] == '\\') {
		fd = -1;
	} else {
		fd = cli_open(&srv->cli, path, flags, DENY_NONE);
	}
	if (fd == -1) {
		/* it might be a directory. Maybe we should use chkpath? */
		eno = smbw_errno(&srv->cli);
		fd = smbw_dir_open(fname);
		if (fd == -1) errno = eno;
		smbw_busy--;
		return fd;
	}

	file = (struct smbw_file *)malloc(sizeof(*file));
	if (!file) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(file);

	file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
	if (!file->f) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(file->f);

	file->f->cli_fd = fd;
	file->f->fname = strdup(path);
	if (!file->f->fname) {
		errno = ENOMEM;
		goto failed;
	}
	file->srv = srv;
	file->fd = open(SMBW_DUMMY, O_WRONLY);
	if (file->fd == -1) {
		errno = EMFILE;
		goto failed;
	}

	if (bitmap_query(smbw_file_bmap, file->fd)) {
		DEBUG(0,("ERROR: fd used in smbw_open\n"));
		errno = EIO;
		goto failed;
	}

	file->f->ref_count=1;

	bitmap_set(smbw_file_bmap, file->fd);

	DLIST_ADD(smbw_files, file);

	DEBUG(4,("opened %s\n", fname));

	smbw_busy--;
	return file->fd;

 failed:
	if (fd != -1) {
		cli_close(&srv->cli, fd);
	}
	if (file) {
		if (file->f) {
			SAFE_FREE(file->f->fname);
			SAFE_FREE(file->f);
		}
		SAFE_FREE(file);
	}
	smbw_busy--;
	return -1;
}
Ejemplo n.º 20
0
SMBCSRV *
SMBC_server(TALLOC_CTX *ctx,
            SMBCCTX *context,
            bool connect_if_not_found,
            const char *server,
            const char *share,
            char **pp_workgroup,
            char **pp_username,
            char **pp_password)
{
	SMBCSRV *srv=NULL;
	char *workgroup = NULL;
	struct cli_state *c;
	struct nmb_name called, calling;
	const char *server_n = server;
	struct sockaddr_storage ss;
	int tried_reverse = 0;
        int port_try_first;
        int port_try_next;
        int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
	uint32 fs_attrs = 0;
        const char *username_used;
 	NTSTATUS status;
        
	zero_sockaddr(&ss);
	ZERO_STRUCT(c);
        
	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}
        
        /* Look for a cached connection */
        srv = SMBC_find_server(ctx, context, server, share,
                               pp_workgroup, pp_username, pp_password);
        
        /*
         * If we found a connection and we're only allowed one share per
         * server...
         */
        if (srv &&
            *share != '\0' &&
            smbc_getOptionOneSharePerServer(context)) {
                
                /*
                 * ... then if there's no current connection to the share,
                 * connect to it.  SMBC_find_server(), or rather the function
                 * pointed to by context->get_cached_srv_fn which
                 * was called by SMBC_find_server(), will have issued a tree
                 * disconnect if the requested share is not the same as the
                 * one that was already connected.
                 */
                if (srv->cli->cnum == (uint16) -1) {
                        /* Ensure we have accurate auth info */
			SMBC_call_auth_fn(ctx, context, server, share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);
                        
			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				cli_shutdown(srv->cli);
				srv->cli = NULL;
				smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
				return NULL;
			}
                        
			/*
			 * We don't need to renegotiate encryption
			 * here as the encryption context is not per
			 * tid.
			 */
                        
			if (!cli_send_tconX(srv->cli, share, "?????",
                                            *pp_password,
                                            strlen(*pp_password)+1)) {
                                
                                errno = SMBC_errno(context, srv->cli);
                                cli_shutdown(srv->cli);
				srv->cli = NULL;
                                smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
                                srv = NULL;
                        }
                        
                        /* Determine if this share supports case sensitivity */
                        if (is_ipc) {
                                DEBUG(4,
                                      ("IPC$ so ignore case sensitivity\n"));
                        } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
                                DEBUG(4, ("Could not retrieve "
                                          "case sensitivity flag: %s.\n",
                                          cli_errstr(c)));

                                /*
                                 * We can't determine the case sensitivity of
                                 * the share. We have no choice but to use the
                                 * user-specified case sensitivity setting.
                                 */
                                if (smbc_getOptionCaseSensitive(context)) {
                                        cli_set_case_sensitive(c, True);
                                } else {
                                        cli_set_case_sensitive(c, False);
                                }
                        } else {
                                DEBUG(4,
                                      ("Case sensitive: %s\n",
                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                        ? "True"
                                        : "False")));
                                cli_set_case_sensitive(
                                        c,
                                        (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                         ? True
                                         : False));
                        }

                        /*
                         * Regenerate the dev value since it's based on both
                         * server and share
                         */
                        if (srv) {
                                srv->dev = (dev_t)(str_checksum(server) ^
                                                   str_checksum(share));
                        }
                }
        }
        
        /* If we have a connection... */
        if (srv) {
                
                /* ... then we're done here.  Give 'em what they came for. */
                goto done;
        }
        
        /* If we're not asked to connect when a connection doesn't exist... */
        if (! connect_if_not_found) {
                /* ... then we're done here. */
                return NULL;
        }
        
	if (!*pp_workgroup || !*pp_username || !*pp_password) {
		errno = ENOMEM;
		return NULL;
	}
        
	make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0);
	make_nmb_name(&called , server, 0x20);
        
	DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));
        
	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
        
again:
        
	zero_sockaddr(&ss);
        
	/* have to open a new connection */
	if ((c = cli_initialise()) == NULL) {
		errno = ENOMEM;
		return NULL;
	}

        if (smbc_getOptionUseKerberos(context)) {
		c->use_kerberos = True;
	}

        if (smbc_getOptionFallbackAfterKerberos(context)) {
		c->fallback_after_kerberos = True;
	}
        
	c->timeout = smbc_getTimeout(context);
        
        /*
         * Force use of port 139 for first try if share is $IPC, empty, or
         * null, so browse lists can work
         */
        if (share == NULL || *share == '\0' || is_ipc) {
                port_try_first = 139;
                port_try_next = 445;
        } else {
                port_try_first = 445;
                port_try_next = 139;
        }
        
        c->port = port_try_first;
        
	status = cli_connect(c, server_n, &ss);
	if (!NT_STATUS_IS_OK(status)) {
                
                /* First connection attempt failed.  Try alternate port. */
                c->port = port_try_next;
                
                status = cli_connect(c, server_n, &ss);
		if (!NT_STATUS_IS_OK(status)) {
			cli_shutdown(c);
			errno = ETIMEDOUT;
			return NULL;
		}
	}
        
	if (!cli_session_request(c, &calling, &called)) {
		cli_shutdown(c);
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		} else {  /* Try one more time, but ensure we don't loop */
                        
			/* Only try this if server is an IP address ... */
                        
			if (is_ipaddress(server) && !tried_reverse) {
				fstring remote_name;
				struct sockaddr_storage rem_ss;
                                
				if (!interpret_string_addr(&rem_ss, server,
                                                           NI_NUMERICHOST)) {
					DEBUG(4, ("Could not convert IP address "
                                                  "%s to struct sockaddr_storage\n",
                                                  server));
					errno = ETIMEDOUT;
					return NULL;
				}
                                
				tried_reverse++; /* Yuck */
                                
				if (name_status_find("*", 0, 0,
                                                     &rem_ss, remote_name)) {
					make_nmb_name(&called,
                                                      remote_name,
                                                      0x20);
					goto again;
				}
			}
		}
		errno = ETIMEDOUT;
		return NULL;
	}
        
	DEBUG(4,(" session request ok\n"));
        
	if (!cli_negprot(c)) {
		cli_shutdown(c);
		errno = ETIMEDOUT;
		return NULL;
	}
        
        username_used = *pp_username;
        
	if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
					       *pp_password,
                                               strlen(*pp_password),
					       *pp_password,
                                               strlen(*pp_password),
					       *pp_workgroup))) {
                
                /* Failed.  Try an anonymous login, if allowed by flags. */
                username_used = "";
                
                if (smbc_getOptionNoAutoAnonymousLogin(context) ||
                    !NT_STATUS_IS_OK(cli_session_setup(c, username_used,
                                                       *pp_password, 1,
                                                       *pp_password, 0,
                                                       *pp_workgroup))) {
                        
                        cli_shutdown(c);
                        errno = EPERM;
                        return NULL;
                }
	}

	cli_init_creds(c, username_used, *pp_workgroup, *pp_password);
        
	DEBUG(4,(" session setup ok\n"));
        
	if (!cli_send_tconX(c, share, "?????",
			    *pp_password, strlen(*pp_password)+1)) {
		errno = SMBC_errno(context, c);
		cli_shutdown(c);
		return NULL;
	}
        
	DEBUG(4,(" tconx ok\n"));
        
        /* Determine if this share supports case sensitivity */
	if (is_ipc) {
                DEBUG(4, ("IPC$ so ignore case sensitivity\n"));
        } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
                DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
                          cli_errstr(c)));

                /*
                 * We can't determine the case sensitivity of the share. We
                 * have no choice but to use the user-specified case
                 * sensitivity setting.
                 */
                if (smbc_getOptionCaseSensitive(context)) {
                        cli_set_case_sensitive(c, True);
                } else {
                        cli_set_case_sensitive(c, False);
                }
	} else {
                DEBUG(4, ("Case sensitive: %s\n",
                          (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                           ? "True"
                           : "False")));
                cli_set_case_sensitive(c,
                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                        ? True
                                        : False));
        }

	if (context->internal->smb_encryption_level) {
		/* Attempt UNIX smb encryption. */
		if (!NT_STATUS_IS_OK(cli_force_encryption(c,
                                                          username_used,
                                                          *pp_password,
                                                          *pp_workgroup))) {
                        
			/*
			 * context->smb_encryption_level == 1
			 * means don't fail if encryption can't be negotiated,
			 * == 2 means fail if encryption can't be negotiated.
			 */
                        
			DEBUG(4,(" SMB encrypt failed\n"));
                        
			if (context->internal->smb_encryption_level == 2) {
	                        cli_shutdown(c);
				errno = EPERM;
				return NULL;
			}
		}
		DEBUG(4,(" SMB encrypt ok\n"));
	}
        
	/*
	 * Ok, we have got a nice connection
	 * Let's allocate a server structure.
	 */
        
	srv = SMB_MALLOC_P(SMBCSRV);
	if (!srv) {
		errno = ENOMEM;
		goto failed;
	}
        
	ZERO_STRUCTP(srv);
	srv->cli = c;
	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
        srv->no_pathinfo = False;
        srv->no_pathinfo2 = False;
        srv->no_nt_session = False;
        
	/* now add it to the cache (internal or external)  */
	/* Let the cache function set errno if it wants to */
	errno = 0;
	if (smbc_getFunctionAddCachedServer(context)(context, srv,
                                                     server, share,
                                                     *pp_workgroup,
                                                     *pp_username)) {
		int saved_errno = errno;
		DEBUG(3, (" Failed to add server to cache\n"));
		errno = saved_errno;
		if (errno == 0) {
			errno = ENOMEM;
		}
		goto failed;
	}
        
	DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
		  server, share, srv));
        
	DLIST_ADD(context->internal->servers, srv);
done:
	if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
		workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
	} else {
		workgroup = *pp_workgroup;
	}
	if(!workgroup) {
		return NULL;
	}
	
	/* set the credentials to make DFS work */
	smbc_set_credentials_with_fallback(context,
					   workgroup,
				    	   *pp_username,
				   	   *pp_password);
	
	return srv;
        
failed:
	cli_shutdown(c);
	if (!srv) {
		return NULL;
	}
        
	SAFE_FREE(srv);
	return NULL;
}
Ejemplo n.º 21
0
/*
  load our local partition list
 */
static WERROR kccsrv_load_partitions(struct kccsrv_service *s)
{
	struct ldb_dn *basedn;
	struct ldb_result *r;
	struct ldb_message_element *el;
	static const char *attrs[] = { "namingContexts", "configurationNamingContext", NULL };
	unsigned int i;
	int ret;

	basedn = ldb_dn_new(s, s->samdb, NULL);
	W_ERROR_HAVE_NO_MEMORY(basedn);

	ret = ldb_search(s->samdb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
			 "(objectClass=*)");
	talloc_free(basedn);
	if (ret != LDB_SUCCESS) {
		return WERR_FOOBAR;
	} else if (r->count != 1) {
		talloc_free(r);
		return WERR_FOOBAR;
	}

	el = ldb_msg_find_element(r->msgs[0], "namingContexts");
	if (!el) {
		return WERR_FOOBAR;
	}

	for (i=0; i < el->num_values; i++) {
		const char *v = (const char *)el->values[i].data;
		struct ldb_dn *pdn;
		struct kccsrv_partition *p;

		pdn = ldb_dn_new(s, s->samdb, v);
		if (!ldb_dn_validate(pdn)) {
			return WERR_FOOBAR;
		}

		p = talloc_zero(s, struct kccsrv_partition);
		W_ERROR_HAVE_NO_MEMORY(p);

		p->dn = talloc_steal(p, pdn);
		p->service = s;

		DLIST_ADD(s->partitions, p);

		DEBUG(2, ("kccsrv_partition[%s] loaded\n", v));
	}

	el = ldb_msg_find_element(r->msgs[0], "configurationNamingContext");
	if (!el) {
		return WERR_FOOBAR;
	}
	s->config_dn = ldb_dn_new(s, s->samdb, (const char *)el->values[0].data);
	if (!ldb_dn_validate(s->config_dn)) {
		return WERR_FOOBAR;
	}

	talloc_free(r);

	return WERR_OK;
}
Ejemplo n.º 22
0
/*
 * Connect to a server for getting/setting attributes, possibly on an existing
 * connection.  This works similarly to SMBC_server().
 */
SMBCSRV *
SMBC_attr_server(TALLOC_CTX *ctx,
                 SMBCCTX *context,
                 const char *server,
                 const char *share,
                 char **pp_workgroup,
                 char **pp_username,
                 char **pp_password)
{
        int flags;
        struct sockaddr_storage ss;
	struct cli_state *ipc_cli;
	struct rpc_pipe_client *pipe_hnd;
        NTSTATUS nt_status;
	SMBCSRV *ipc_srv=NULL;
        
        /*
         * See if we've already created this special connection.  Reference
         * our "special" share name '*IPC$', which is an impossible real share
         * name due to the leading asterisk.
         */
        ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
                                   pp_workgroup, pp_username, pp_password);
        if (!ipc_srv) {
                
                /* We didn't find a cached connection.  Get the password */
		if (!*pp_password || (*pp_password)[0] == '\0') {
                        /* ... then retrieve it now. */
			SMBC_call_auth_fn(ctx, context, server, share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);
			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				return NULL;
			}
                }
                
                flags = 0;
                if (smbc_getOptionUseKerberos(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
                }
                
                zero_sockaddr(&ss);
                nt_status = cli_full_connection(&ipc_cli,
						global_myname(), server,
						&ss, 0, "IPC$", "?????",
						*pp_username,
						*pp_workgroup,
						*pp_password,
						flags,
						Undefined, NULL);
                if (! NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("cli_full_connection failed! (%s)\n",
                                 nt_errstr(nt_status)));
                        errno = ENOTSUP;
                        return NULL;
                }
                
		if (context->internal->smb_encryption_level) {
			/* Attempt UNIX smb encryption. */
			if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
                                                                  *pp_username,
                                                                  *pp_password,
                                                                  *pp_workgroup))) {
                                
				/*
				 * context->smb_encryption_level ==
				 * 1 means don't fail if encryption can't be
				 * negotiated, == 2 means fail if encryption
				 * can't be negotiated.
				 */
                                
				DEBUG(4,(" SMB encrypt failed on IPC$\n"));
                                
				if (context->internal->smb_encryption_level == 2) {
		                        cli_shutdown(ipc_cli);
					errno = EPERM;
					return NULL;
				}
			}
			DEBUG(4,(" SMB encrypt ok on IPC$\n"));
		}
                
                ipc_srv = SMB_MALLOC_P(SMBCSRV);
                if (!ipc_srv) {
                        errno = ENOMEM;
                        cli_shutdown(ipc_cli);
                        return NULL;
                }
                
                ZERO_STRUCTP(ipc_srv);
                ipc_srv->cli = ipc_cli;
                
                nt_status = cli_rpc_pipe_open_noauth(
			ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1, ("cli_nt_session_open fail!\n"));
                        errno = ENOTSUP;
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }
                
                /*
                 * Some systems don't support
                 * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
                 * so we might as well do it too.
                 */
                
                nt_status = rpccli_lsa_open_policy(
                        pipe_hnd,
                        talloc_tos(),
                        True,
                        GENERIC_EXECUTE_ACCESS,
                        &ipc_srv->pol);
                
                if (!NT_STATUS_IS_OK(nt_status)) {
                        errno = SMBC_errno(context, ipc_srv->cli);
                        cli_shutdown(ipc_srv->cli);
                        return NULL;
                }
                
                /* now add it to the cache (internal or external) */
                
                errno = 0;      /* let cache function set errno if it likes */
                if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv,
                                                             server,
                                                             "*IPC$",
                                                             *pp_workgroup,
                                                             *pp_username)) {
                        DEBUG(3, (" Failed to add server to cache\n"));
                        if (errno == 0) {
                                errno = ENOMEM;
                        }
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }
                
                DLIST_ADD(context->internal->servers, ipc_srv);
        }
        
        return ipc_srv;
}
Ejemplo n.º 23
0
static int aicloud_connection_smb_info_init(server *srv, connection *con, plugin_data *p) 
{
	UNUSED(srv);

	char pWorkgroup[30]={0};
	char pServer[64]={0};
	char pShare[1280]={0};
	char pPath[1280]={0};
		
	smbc_wrapper_parse_path2(con, pWorkgroup, pServer, pShare, pPath);
	
	buffer* bworkgroup = buffer_init();
	buffer* bserver = buffer_init();
	buffer* bshare = buffer_init();
	buffer* bpath = buffer_init();
	URI_QUERY_TYPE qflag = SMB_FILE_QUERY;
	
	if(pWorkgroup[0] != '\0')
		buffer_copy_string(bworkgroup, pWorkgroup);
	
	if(pServer[0] != '\0') {		
		int isHost = smbc_check_connectivity(con->physical_auth_url->ptr);
		if(isHost) {
			buffer_copy_string(bserver, pServer);
		}
		else{
			buffer_free(bworkgroup);
			buffer_free(bserver);
			buffer_free(bshare);
			buffer_free(bpath);
			return 2;
		}
	} 
	else {
		if(qflag == SMB_FILE_QUERY) {
			qflag = SMB_HOST_QUERY;
		}
	}
	
	if(pServer[0] != '\0' && pShare[0] != '\0') {
		buffer_copy_string(bshare, pShare);
	} 
	else {
		if(qflag == SMB_FILE_QUERY)  {
			qflag = SMB_SHARE_QUERY;
		}
	}
	
	if(pServer[0] != '\0' && pShare[0] != '\0' && pPath[0] != '\0') {
		buffer_copy_string(bpath, pPath);
		qflag = SMB_FILE_QUERY;
	}

	data_string *ds = (data_string *)array_get_element(con->request.headers, "user-Agent");

	smb_info_t *smb_info;

	if( ds && 
	    ( strstr( ds->value->ptr, "Mozilla" ) || 
	      strstr( ds->value->ptr, "Opera" ) || 
	      con->mode == SMB_NTLM ) ){
	    
		//- From browser, like IE, Chrome, Firefox, Safari		
		if(smb_info = smbdav_get_smb_info_from_pool(srv, con, p)){ 
			Cdbg(DBE, "Get smb_info from pool smb_info->qflag=[%d], smb_info->user=[%s], smb_info->pass=[%s]", 
				smb_info->qflag, smb_info->username->ptr, smb_info->password->ptr);
		}
		else{
			smb_info = calloc(1, sizeof(smb_info_t));
			smb_info->username = buffer_init();
			smb_info->password = buffer_init();
			smb_info->workgroup = buffer_init();
			smb_info->server = buffer_init();
			smb_info->share = buffer_init();
			smb_info->path = buffer_init();
			smb_info->user_agent = buffer_init();
			smb_info->src_ip = buffer_init();			
			
			if(con->mode == SMB_NTLM){
				smb_info->cli = smbc_cli_initialize();
				if(!buffer_is_empty(bserver)){
					smbc_cli_connect(smb_info->cli, bserver->ptr, SMB_PORT);
				}
				smb_info->ntlmssp_state = NULL; 
				smb_info->state = NTLMSSP_INITIAL;
			}

			DLIST_ADD(p->smb_info_list, smb_info);			
		}	
		con->smb_info = smb_info;
			
	}
	else{		
		smb_info = calloc(1, sizeof(smb_info_t));
		smb_info->username = buffer_init();
		smb_info->password = buffer_init();
		smb_info->workgroup = buffer_init();
		smb_info->server = buffer_init();
		smb_info->share = buffer_init();
		smb_info->path = buffer_init();
		smb_info->user_agent = buffer_init();
		smb_info->src_ip = buffer_init();			
		
		con->smb_info = smb_info;
	}
	
	con->smb_info->auth_time = time(NULL);	
	con->smb_info->auth_right = 0;

	if(ds)
		buffer_copy_string(con->smb_info->user_agent, ds->value->ptr);
	
	con->smb_info->qflag = qflag;
	buffer_copy_string_buffer(con->smb_info->workgroup, bworkgroup);
	buffer_copy_string_buffer(con->smb_info->server, bserver);
	buffer_copy_string_buffer(con->smb_info->share, bshare);
	buffer_copy_string_buffer(con->smb_info->path, bpath);
	buffer_copy_string_buffer(con->smb_info->src_ip, con->dst_addr_buf);

	Cdbg(DBE, "con->smb_info->workgroup=[%s]", con->smb_info->workgroup->ptr);
	Cdbg(DBE, "con->smb_info->server=[%s]", con->smb_info->server->ptr);
	Cdbg(DBE, "con->smb_info->share=[%s]", con->smb_info->share->ptr);
	Cdbg(DBE, "con->smb_info->path=[%s]", con->smb_info->path->ptr);
	Cdbg(DBE, "con->smb_info->user_agent=[%s]", con->smb_info->user_agent->ptr);
	Cdbg(DBE, "con->smb_info->src_ip=[%s]", con->smb_info->src_ip->ptr);
	Cdbg(DBE, "con->smb_info->qflag=[%d]", con->smb_info->qflag);
		
	buffer_free(bworkgroup);
	buffer_free(bserver);
	buffer_free(bshare);
	buffer_free(bpath);

	return 1;
}
Ejemplo n.º 24
0
/*
  wrapped connection to a ldb database
  to close just talloc_free() the returned ldb_context

  TODO:  We need an error_string parameter
 */
struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
				     struct tevent_context *ev,
				     struct loadparm_context *lp_ctx,
				     const char *url,
				     struct auth_session_info *session_info,
				     struct cli_credentials *credentials,
				     unsigned int flags)
{
	struct ldb_context *ldb;
	int ret;
	char *real_url = NULL;
	struct ldb_wrap *w;
	struct ldb_wrap_context c;

	c.url          = url;
	c.ev           = ev;
	c.lp_ctx       = lp_ctx;
	c.session_info = session_info;
	c.credentials  = credentials;
	c.flags        = flags;

	/* see if we can re-use an existing ldb */
	for (w=ldb_wrap_list; w; w=w->next) {
		if (ldb_wrap_same_context(&c, &w->context)) {
			return talloc_reference(mem_ctx, w->ldb);
		}
	}

	/* we want to use the existing event context if possible. This
	   relies on the fact that in smbd, everything is a child of
	   the main event_context */
	if (ev == NULL) {
		return NULL;
	}

	ldb = ldb_init(mem_ctx, ev);
	if (ldb == NULL) {
		return NULL;
	}

	ldb_set_modules_dir(ldb,
			    talloc_asprintf(ldb,
					    "%s/ldb",
					    lp_modulesdir(lp_ctx)));

	if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
		talloc_free(ldb);
		return NULL;
	}

	if (ldb_set_opaque(ldb, "credentials", credentials)) {
		talloc_free(ldb);
		return NULL;
	}

	if (ldb_set_opaque(ldb, "loadparm", lp_ctx)) {
		talloc_free(ldb);
		return NULL;
	}

	/* This must be done before we load the schema, as these
	 * handlers for objectSid and objectGUID etc must take
	 * precedence over the 'binary attribute' declaration in the
	 * schema */
	ret = ldb_register_samba_handlers(ldb);
	if (ret == -1) {
		talloc_free(ldb);
		return NULL;
	}

	if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
		dsdb_set_global_schema(ldb);
	}

	ldb_set_debug(ldb, ldb_wrap_debug, NULL);

	ldb_set_utf8_fns(ldb, NULL, wrap_casefold);

	real_url = private_path(ldb, lp_ctx, url);
	if (real_url == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	/* allow admins to force non-sync ldb for all databases */
	if (lp_parm_bool(lp_ctx, NULL, "ldb", "nosync", false)) {
		flags |= LDB_FLG_NOSYNC;
	}

	if (DEBUGLVL(10)) {
		flags |= LDB_FLG_ENABLE_TRACING;
	}

	/* we usually want Samba databases to be private. If we later
	   find we need one public, we will need to add a parameter to
	   ldb_wrap_connect() */
	ldb_set_create_perms(ldb, 0600);
	
	ret = ldb_connect(ldb, real_url, flags, NULL);
	if (ret != LDB_SUCCESS) {
		talloc_free(ldb);
		return NULL;
	}

	/* setup for leak detection */
	ldb_set_opaque(ldb, "wrap_url", real_url);
	
	/* add to the list of open ldb contexts */
	w = talloc(ldb, struct ldb_wrap);
	if (w == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	w->context = c;
	w->context.url = talloc_strdup(w, url);
	if (w->context.url == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	w->ldb = ldb;

	DLIST_ADD(ldb_wrap_list, w);

	/* make the resulting schema global */
	if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
		dsdb_make_schema_global(ldb);
	}

	DEBUG(3,("ldb_wrap open of %s\n", url));

	talloc_set_destructor(w, ldb_wrap_destructor);

	return ldb;
}
Ejemplo n.º 25
0
static SMBCSRV *
SMBC_server_internal(TALLOC_CTX *ctx,
            SMBCCTX *context,
            bool connect_if_not_found,
            const char *server,
            uint16_t port,
            const char *share,
            char **pp_workgroup,
            char **pp_username,
            char **pp_password,
	    bool *in_cache)
{
	SMBCSRV *srv=NULL;
	char *workgroup = NULL;
	struct cli_state *c = NULL;
	const char *server_n = server;
        int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
	uint32_t fs_attrs = 0;
	const char *username_used = NULL;
	const char *password_used = NULL;
 	NTSTATUS status;
	char *newserver, *newshare;
	int flags = 0;
	struct smbXcli_tcon *tcon = NULL;
	int signing_state = SMB_SIGNING_DEFAULT;
	struct cli_credentials *creds = NULL;
	bool use_kerberos = false;
	bool fallback_after_kerberos = false;
	bool use_ccache = false;
	bool pw_nt_hash = false;

	ZERO_STRUCT(c);
	*in_cache = false;

	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}

        /* Look for a cached connection */
        srv = SMBC_find_server(ctx, context, server, share,
                               pp_workgroup, pp_username, pp_password);

        /*
         * If we found a connection and we're only allowed one share per
         * server...
         */
        if (srv &&
	    share != NULL && *share != '\0' &&
            smbc_getOptionOneSharePerServer(context)) {

                /*
                 * ... then if there's no current connection to the share,
                 * connect to it.  SMBC_find_server(), or rather the function
                 * pointed to by context->get_cached_srv_fn which
                 * was called by SMBC_find_server(), will have issued a tree
                 * disconnect if the requested share is not the same as the
                 * one that was already connected.
                 */

		/*
		 * Use srv->cli->desthost and srv->cli->share instead of
		 * server and share below to connect to the actual share,
		 * i.e., a normal share or a referred share from
		 * 'msdfs proxy' share.
		 */
                if (!cli_state_has_tcon(srv->cli)) {
                        /* Ensure we have accurate auth info */
			SMBC_call_auth_fn(ctx, context,
					  smbXcli_conn_remote_name(srv->cli->conn),
					  srv->cli->share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);

			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				cli_shutdown(srv->cli);
				srv->cli = NULL;
				smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
				return NULL;
			}

			/*
			 * We don't need to renegotiate encryption
			 * here as the encryption context is not per
			 * tid.
			 */

			status = cli_tree_connect(srv->cli,
						  srv->cli->share,
						  "?????",
						  *pp_password);
			if (!NT_STATUS_IS_OK(status)) {
                                errno = map_errno_from_nt_status(status);
                                cli_shutdown(srv->cli);
				srv->cli = NULL;
                                smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
                                srv = NULL;
                        }

                        /* Determine if this share supports case sensitivity */
                        if (is_ipc) {
                                DEBUG(4,
                                      ("IPC$ so ignore case sensitivity\n"));
                                status = NT_STATUS_OK;
                        } else {
                                status = cli_get_fs_attr_info(c, &fs_attrs);
                        }

                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(4, ("Could not retrieve "
                                          "case sensitivity flag: %s.\n",
                                          nt_errstr(status)));

                                /*
                                 * We can't determine the case sensitivity of
                                 * the share. We have no choice but to use the
                                 * user-specified case sensitivity setting.
                                 */
                                if (smbc_getOptionCaseSensitive(context)) {
                                        cli_set_case_sensitive(c, True);
                                } else {
                                        cli_set_case_sensitive(c, False);
                                }
                        } else if (!is_ipc) {
                                DEBUG(4,
                                      ("Case sensitive: %s\n",
                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                        ? "True"
                                        : "False")));
                                cli_set_case_sensitive(
                                        c,
                                        (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                         ? True
                                         : False));
                        }

                        /*
                         * Regenerate the dev value since it's based on both
                         * server and share
                         */
                        if (srv) {
				const char *remote_name =
					smbXcli_conn_remote_name(srv->cli->conn);

				srv->dev = (dev_t)(str_checksum(remote_name) ^
                                                   str_checksum(srv->cli->share));
                        }
                }
        }

        /* If we have a connection... */
        if (srv) {

                /* ... then we're done here.  Give 'em what they came for. */
		*in_cache = true;
                goto done;
        }

        /* If we're not asked to connect when a connection doesn't exist... */
        if (! connect_if_not_found) {
                /* ... then we're done here. */
                return NULL;
        }

	if (!*pp_workgroup || !*pp_username || !*pp_password) {
		errno = ENOMEM;
		return NULL;
	}

	DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));

	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));

	status = NT_STATUS_UNSUCCESSFUL;

	if (smbc_getOptionUseKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
		use_kerberos = true;
	}

	if (smbc_getOptionFallbackAfterKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
		fallback_after_kerberos = true;
	}

	if (smbc_getOptionUseCCache(context)) {
		flags |= CLI_FULL_CONNECTION_USE_CCACHE;
		use_ccache = true;
	}

	if (smbc_getOptionUseNTHash(context)) {
		flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
		pw_nt_hash = true;
	}

	if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
		signing_state = SMB_SIGNING_REQUIRED;
	}

	if (port == 0) {
	        if (share == NULL || *share == '\0' || is_ipc) {
			/*
			 * Try 139 first for IPC$
			 */
			status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
					smbc_getNetbiosName(context),
					signing_state, flags, &c);
		}
	}

	if (!NT_STATUS_IS_OK(status)) {
		/*
		 * No IPC$ or 139 did not work
		 */
		status = cli_connect_nb(server_n, NULL, port, 0x20,
					smbc_getNetbiosName(context),
					signing_state, flags, &c);
	}

	if (!NT_STATUS_IS_OK(status)) {
		errno = map_errno_from_nt_status(status);
		return NULL;
	}

	cli_set_timeout(c, smbc_getTimeout(context));

	status = smbXcli_negprot(c->conn, c->timeout,
				 lp_client_min_protocol(),
				 lp_client_max_protocol());
	if (!NT_STATUS_IS_OK(status)) {
		cli_shutdown(c);
		errno = ETIMEDOUT;
		return NULL;
	}

	if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
		/* Ensure we ask for some initial credits. */
		smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
	}

	username_used = *pp_username;
	password_used = *pp_password;

	creds = cli_session_creds_init(c,
				       username_used,
				       *pp_workgroup,
				       NULL, /* realm */
				       password_used,
				       use_kerberos,
				       fallback_after_kerberos,
				       use_ccache,
				       pw_nt_hash);
	if (creds == NULL) {
		cli_shutdown(c);
		errno = ENOMEM;
		return NULL;
	}

	status = cli_session_setup_creds(c, creds);
	if (!NT_STATUS_IS_OK(status)) {

                /* Failed.  Try an anonymous login, if allowed by flags. */
		username_used = "";
		password_used = "";

                if (smbc_getOptionNoAutoAnonymousLogin(context) ||
		    !NT_STATUS_IS_OK(cli_session_setup_anon(c))) {

                        cli_shutdown(c);
                        errno = EPERM;
                        return NULL;
                }
	}

	DEBUG(4,(" session setup ok\n"));

	/* here's the fun part....to support 'msdfs proxy' shares
	   (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
	   here before trying to connect to the original share.
	   cli_check_msdfs_proxy() will fail if it is a normal share. */

	if (smbXcli_conn_dfs_supported(c->conn) &&
			cli_check_msdfs_proxy(ctx, c, share,
				&newserver, &newshare,
				/* FIXME: cli_check_msdfs_proxy() does
				   not support smbc_smb_encrypt_level type */
				context->internal->smb_encryption_level ?
					true : false,
				creds)) {
		cli_shutdown(c);
		srv = SMBC_server_internal(ctx, context, connect_if_not_found,
				newserver, port, newshare, pp_workgroup,
				pp_username, pp_password, in_cache);
		TALLOC_FREE(newserver);
		TALLOC_FREE(newshare);
		return srv;
	}

	/* must be a normal share */

	status = cli_tree_connect_creds(c, share, "?????", creds);
	if (!NT_STATUS_IS_OK(status)) {
		errno = map_errno_from_nt_status(status);
		cli_shutdown(c);
		return NULL;
	}

	DEBUG(4,(" tconx ok\n"));

	if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
		tcon = c->smb2.tcon;
	} else {
		tcon = c->smb1.tcon;
	}

        /* Determine if this share supports case sensitivity */
	if (is_ipc) {
                DEBUG(4, ("IPC$ so ignore case sensitivity\n"));
                status = NT_STATUS_OK;
        } else {
                status = cli_get_fs_attr_info(c, &fs_attrs);
        }

        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
                          nt_errstr(status)));

                /*
                 * We can't determine the case sensitivity of the share. We
                 * have no choice but to use the user-specified case
                 * sensitivity setting.
                 */
                if (smbc_getOptionCaseSensitive(context)) {
                        cli_set_case_sensitive(c, True);
                } else {
                        cli_set_case_sensitive(c, False);
                }
	} else if (!is_ipc) {
                DEBUG(4, ("Case sensitive: %s\n",
                          (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                           ? "True"
                           : "False")));
		smbXcli_tcon_set_fs_attributes(tcon, fs_attrs);
        }

	if (context->internal->smb_encryption_level) {
		/* Attempt encryption. */
		status = cli_cm_force_encryption_creds(c,
						       creds,
						       share);
		if (!NT_STATUS_IS_OK(status)) {

			/*
			 * context->smb_encryption_level == 1
			 * means don't fail if encryption can't be negotiated,
			 * == 2 means fail if encryption can't be negotiated.
			 */

			DEBUG(4,(" SMB encrypt failed\n"));

			if (context->internal->smb_encryption_level == 2) {
	                        cli_shutdown(c);
				errno = EPERM;
				return NULL;
			}
		}
		DEBUG(4,(" SMB encrypt ok\n"));
	}

	/*
	 * Ok, we have got a nice connection
	 * Let's allocate a server structure.
	 */

	srv = SMB_MALLOC_P(SMBCSRV);
	if (!srv) {
		cli_shutdown(c);
		errno = ENOMEM;
		return NULL;
	}

	ZERO_STRUCTP(srv);
	DLIST_ADD(srv->cli, c);
	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
        srv->no_pathinfo = False;
        srv->no_pathinfo2 = False;
	srv->no_pathinfo3 = False;
        srv->no_nt_session = False;

done:
	if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
		workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
	} else {
		workgroup = *pp_workgroup;
	}
	if(!workgroup) {
		if (c != NULL) {
			cli_shutdown(c);
		}
		SAFE_FREE(srv);
		return NULL;
	}

	/* set the credentials to make DFS work */
	smbc_set_credentials_with_fallback(context,
					   workgroup,
				    	   *pp_username,
				   	   *pp_password);

	return srv;
}
Ejemplo n.º 26
0
int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
{
	struct passwd *usr;
	TALLOC_CTX *mem_ctx = NULL;

	if (!fsp||!fsp->conn||!qt_list)
		return (-1);

	*qt_list = NULL;

	if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
		DEBUG(0,("talloc_init() failed\n"));
		return (-1);
	}

	sys_setpwent();
	while ((usr = sys_getpwent()) != NULL) {
		SMB_NTQUOTA_STRUCT tmp_qt;
		SMB_NTQUOTA_LIST *tmp_list_ent;
		DOM_SID	sid;

		ZERO_STRUCT(tmp_qt);

		if (allready_in_quota_list((*qt_list),usr->pw_uid)) {
			DEBUG(5,("record for uid[%ld] allready in the list\n",(long)usr->pw_uid));
			continue;
		}

		uid_to_sid(&sid, usr->pw_uid);

		if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) {
			DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
				sid_string_static(&sid),fsp->conn->connectpath));
			continue;
		}

		DEBUG(15,("quota entry for id[%s] path[%s]\n",
			sid_string_static(&sid),fsp->conn->connectpath));

		if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			*qt_list = NULL;
			talloc_destroy(mem_ctx);
			return (-1);
		}

		if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			*qt_list = NULL;
			talloc_destroy(mem_ctx);
			return (-1);
		}

		tmp_list_ent->uid = usr->pw_uid;
		memcpy(tmp_list_ent->quotas,&tmp_qt,sizeof(tmp_qt));
		tmp_list_ent->mem_ctx = mem_ctx;

		DLIST_ADD((*qt_list),tmp_list_ent);
		
	}
	sys_endpwent();

	return 0;
}
Ejemplo n.º 27
0
struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
					      const struct ndr_syntax_id *syntax,
					      const struct tsocket_address *remote_address,
					      const struct tsocket_address *local_address,
					      const struct auth_session_info *session_info,
					      struct messaging_context *msg_ctx)
{
	struct pipes_struct *p;
	struct pipe_rpc_fns *context_fns;
	const char *pipe_name;
	int ret;
	const struct ndr_interface_table *table;

	table = ndr_table_by_uuid(&syntax->uuid);
	if (table == NULL) {
		DEBUG(0,("unknown interface\n"));
		return NULL;
	}

	pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table);

	DEBUG(4,("Create pipe requested %s\n", pipe_name));

	ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
				     NCALRPC, RPC_LITTLE_ENDIAN,
				     remote_address, local_address, &p);
	if (ret) {
		DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
		return NULL;
	}

	if (!init_pipe_handles(p, syntax)) {
		DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
		TALLOC_FREE(p);
		return NULL;
	}

	p->session_info = copy_session_info(p, session_info);
	if (p->session_info == NULL) {
		DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n"));
		close_policy_by_pipe(p);
		TALLOC_FREE(p);
		return NULL;
	}

	context_fns = talloc_zero(p, struct pipe_rpc_fns);
	if (context_fns == NULL) {
		DEBUG(0,("talloc() failed!\n"));
		TALLOC_FREE(p);
		return NULL;
	}

	context_fns->next = context_fns->prev = NULL;
	context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(syntax);
	context_fns->cmds = rpc_srv_get_pipe_cmds(syntax);
	context_fns->context_id = 0;
	context_fns->syntax = *syntax;

	/* add to the list of open contexts */
	DLIST_ADD(p->contexts, context_fns);

	DEBUG(4,("Created internal pipe %s\n", pipe_name));

	return p;
}
Ejemplo n.º 28
0
struct dsdb_schema *dsdb_schema_copy_shallow(TALLOC_CTX *mem_ctx,
					     struct ldb_context *ldb,
					     const struct dsdb_schema *schema)
{
	int ret;
	struct dsdb_class *cls;
	struct dsdb_attribute *attr;
	struct dsdb_schema *schema_copy;

	schema_copy = dsdb_new_schema(mem_ctx);
	if (!schema_copy) {
		return NULL;
	}

	/* schema base_dn */
	schema_copy->base_dn = ldb_dn_copy(schema_copy, schema->base_dn);
	if (!schema_copy->base_dn) {
		goto failed;
	}

	/* copy prexiMap & schemaInfo */
	schema_copy->prefixmap = dsdb_schema_pfm_copy_shallow(schema_copy,
							      schema->prefixmap);
	if (!schema_copy->prefixmap) {
		goto failed;
	}

	schema_copy->schema_info = talloc_strdup(schema_copy, schema->schema_info);

	/* copy classes and attributes*/
	for (cls = schema->classes; cls; cls = cls->next) {
		struct dsdb_class *class_copy = talloc_memdup(schema_copy,
							      cls, sizeof(*cls));
		if (!class_copy) {
			goto failed;
		}
		DLIST_ADD(schema_copy->classes, class_copy);
	}
	schema_copy->num_classes = schema->num_classes;

	for (attr = schema->attributes; attr; attr = attr->next) {
		struct dsdb_attribute *a_copy = talloc_memdup(schema_copy,
							      attr, sizeof(*attr));
		if (!a_copy) {
			goto failed;
		}
		DLIST_ADD(schema_copy->attributes, a_copy);
	}
	schema_copy->num_attributes = schema->num_attributes;

	/* rebuild indexes */
	ret = dsdb_setup_sorted_accessors(ldb, schema_copy);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	/* leave reload_seq_number = 0 so it will be refresh ASAP */
	schema_copy->refresh_fn = schema->refresh_fn;
	schema_copy->loaded_from_module = schema->loaded_from_module;

	return schema_copy;

failed:
	talloc_free(schema_copy);
	return NULL;
}
Ejemplo n.º 29
0
/*
  add a watch. The watch is removed when the caller calls
  talloc_free() on *handle
*/
NTSTATUS inotify_watch(struct sys_notify_context *ctx,
                       const char *path,
                       uint32_t *filter,
                       uint32_t *subdir_filter,
                       void (*callback)(struct sys_notify_context *ctx,
                                        void *private_data,
                                        struct notify_event *ev),
                       void *private_data,
                       void *handle_p)
{
    struct inotify_private *in;
    int wd;
    uint32_t mask;
    struct inotify_watch_context *w;
    uint32_t orig_filter = *filter;
    void **handle = (void **)handle_p;

    /* maybe setup the inotify fd */
    if (ctx->private_data == NULL) {
        NTSTATUS status;
        status = inotify_setup(ctx);
        NT_STATUS_NOT_OK_RETURN(status);
    }

    in = talloc_get_type(ctx->private_data, struct inotify_private);

    mask = inotify_map(filter);
    if (mask == 0) {
        /* this filter can't be handled by inotify */
        return NT_STATUS_INVALID_PARAMETER;
    }

    /* using IN_MASK_ADD allows us to cope with inotify() returning the same
       watch descriptor for multiple watches on the same path */
    mask |= (IN_MASK_ADD | IN_ONLYDIR);

    /* get a new watch descriptor for this path */
    wd = inotify_add_watch(in->fd, path, mask);
    if (wd == -1) {
        *filter = orig_filter;
        DEBUG(1, ("inotify_add_watch returned %s\n", strerror(errno)));
        return map_nt_error_from_unix(errno);
    }

    DEBUG(10, ("inotify_add_watch for %s mask %x returned wd %d\n",
               path, mask, wd));

    w = talloc(in, struct inotify_watch_context);
    if (w == NULL) {
        inotify_rm_watch(in->fd, wd);
        *filter = orig_filter;
        return NT_STATUS_NO_MEMORY;
    }

    w->in = in;
    w->wd = wd;
    w->callback = callback;
    w->private_data = private_data;
    w->mask = mask;
    w->filter = orig_filter;
    w->path = talloc_strdup(w, path);
    if (w->path == NULL) {
        inotify_rm_watch(in->fd, wd);
        *filter = orig_filter;
        return NT_STATUS_NO_MEMORY;
    }

    (*handle) = w;

    DLIST_ADD(in->watches, w);

    /* the caller frees the handle to stop watching */
    talloc_set_destructor(w, watch_destructor);

    return NT_STATUS_OK;
}
Ejemplo n.º 30
0
static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
					    const char *server_name,
					    struct client_ipc_connection **pp)
{
	struct libnetapi_private_ctx *priv_ctx;
	struct user_auth_info *auth_info = NULL;
	struct cli_state *cli_ipc = NULL;
	struct client_ipc_connection *p;
	NTSTATUS status;

	if (!ctx || !pp || !server_name) {
		return WERR_INVALID_PARAMETER;
	}

	priv_ctx = (struct libnetapi_private_ctx *)ctx->private_data;

	p = ipc_cm_find(priv_ctx, server_name);
	if (p) {
		*pp = p;
		return WERR_OK;
	}

	auth_info = user_auth_info_init(ctx);
	if (!auth_info) {
		return WERR_NOT_ENOUGH_MEMORY;
	}
	auth_info->signing_state = SMB_SIGNING_IPC_DEFAULT;
	set_cmdline_auth_info_use_kerberos(auth_info, ctx->use_kerberos);
	set_cmdline_auth_info_username(auth_info, ctx->username);
	if (ctx->password) {
		set_cmdline_auth_info_password(auth_info, ctx->password);
	} else {
		set_cmdline_auth_info_getpass(auth_info);
	}

	if (ctx->username && ctx->username[0] &&
	    ctx->password && ctx->password[0] &&
	    ctx->use_kerberos) {
		set_cmdline_auth_info_fallback_after_kerberos(auth_info, true);
	}

	if (ctx->use_ccache) {
		set_cmdline_auth_info_use_ccache(auth_info, true);
	}

	status = cli_cm_open(ctx, NULL,
			     server_name, "IPC$",
			     auth_info,
			     false, false,
			     lp_client_max_protocol(),
			     0, 0x20, &cli_ipc);
	if (!NT_STATUS_IS_OK(status)) {
		cli_ipc = NULL;
	}
	TALLOC_FREE(auth_info);

	if (!cli_ipc) {
		libnetapi_set_error_string(ctx,
			"Failed to connect to IPC$ share on %s", server_name);
		return WERR_CAN_NOT_COMPLETE;
	}

	p = talloc_zero(ctx, struct client_ipc_connection);
	if (p == NULL) {
		return WERR_NOT_ENOUGH_MEMORY;
	}

	p->cli = cli_ipc;
	DLIST_ADD(priv_ctx->ipc_connections, p);

	*pp = p;

	return WERR_OK;
}