794 lines · 17.0 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include "cifs.h"#include "remsmb.h"#include "apinums.h" static Pkt *thdr(Session *s, Share *sp){	Pkt *p; 	p = cifshdr(s, sp, SMB_COM_TRANSACTION);	p->tbase = pl16(p, 0);	/* 0  Total parameter bytes to be sent, filled later */	pl16(p, 0);		/* 2  Total data bytes to be sent, filled later */	pl16(p, 64);			/* 4  Max parameter to return */	pl16(p, MTU - T2HDRLEN - 128);	/* 6  Max data to return */	pl16(p, 1);			/* 8  Max setup count to return */	pl16(p, 0);			/* 10 Flags */	pl32(p, 1000);			/* 12 Timeout (ms) */	pl16(p, 0);			/* 16 Reserved */	pl16(p, 0);			/* 18 Parameter count, filled later */	pl16(p, 0);			/* 20 Parameter offset, filled later */	pl16(p, 0);			/* 22 Data count, filled later */	pl16(p, 0);			/* 24 Data offset, filled later */	pl16(p, 0);			/* 26 Setup count (in words) */	pbytes(p);			/* end of cifs words section */	return p;} static voidptparam(Pkt *p){	uchar *pos; 	if(((p->pos - p->tbase) % 2) != 0)		p8(p, 0);			/* pad to word boundry */	pos = p->pos;	p->pos = p->tbase + 20;	pl16(p, pos - p->buf - NBHDRLEN);	/* param offset */	p->tparam = p->pos = pos;} static voidptdata(Pkt *p){	uchar *pos = p->pos; 	assert(p->tparam != 0);	if(((p->pos - p->tbase) % 2) != 0)		p8(p, 0);		/* pad to word boundry */ 	p->pos = p->tbase + 0;	pl16(p, pos - p->tparam);	/* total param count */ 	p->pos = p->tbase + 18;	pl16(p, pos - p->tparam);	/* param count */ 	p->pos = p->tbase + 24;	pl16(p, pos - p->buf - NBHDRLEN); /* data offset */ 	p->tdata = p->pos = pos;} static inttrpc(Pkt *p){	int got;	uchar *pos = p->pos; 	assert(p->tbase != 0);	assert(p->tdata != 0); 	p->pos = p->tbase + 2;	pl16(p, pos - p->tdata);	/* total data count */ 	p->pos = p->tbase + 22;	pl16(p, pos - p->tdata);	/* data count */ 	p->pos = pos;	if((got = cifsrpc(p)) == -1)		return -1; 	gl16(p);			/* Total parameter count */	gl16(p);			/* Total data count */	gl16(p);			/* Reserved */	gl16(p);			/* Parameter count in this buffer */	p->tparam = p->buf + NBHDRLEN + gl16(p); /* Parameter offset */	gl16(p);			/* Parameter displacement */	gl16(p);			/* Data count (this buffer); */	p->tdata = p->buf + NBHDRLEN + gl16(p); /* Data offset */	gl16(p);			/* Data displacement */	g8(p);				/* Setup count */	g8(p);				/* Reserved */	return got;} static voidgtparam(Pkt *p){	p->pos = p->tparam;} static voidgtdata(Pkt *p){	p->pos = p->tdata;}  intRAPshareenum(Session *s, Share *sp, Share **ent){	int ngot = 0, err, navail, nret;	char tmp[1024];	Pkt *p;	Share *q; 	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WShareEnum);	pascii(p, REMSmb_NetShareEnum_P);	/* request descriptor */	pascii(p, REMSmb_share_info_0);		/* reply descriptor */	pl16(p, 0);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	gl16(p);				/* rx buffer offset */	nret = gl16(p);				/* number of entries returned */	navail = gl16(p);			/* number of entries available */ 	if(err && err != RAP_ERR_MOREINFO){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	if(ngot == 0){		*ent = emalloc9p(sizeof(Share) * navail);		memset(*ent, 0, sizeof(Share) * navail);	} 	q = *ent + ngot;	for (; ngot < navail && nret--; ngot++){		gmem(p, tmp, 13); 		/* name */		tmp[13] = 0;		q->name = estrdup9p(tmp);		q++;	} 	if(ngot < navail)		fprint(2, "%s: %d/%d - share list incomplete\n", argv0, ngot, navail); 	free(p);	return ngot;}  intRAPshareinfo(Session *s, Share *sp, char *share, Shareinfo2 *si2p){	int conv, err;	char tmp[1024];	Pkt *p; 	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN"); 	ptparam(p);	pl16(p, API_WShareGetInfo);	pascii(p, REMSmb_NetShareGetInfo_P);	/* request descriptor */	pascii(p, REMSmb_share_info_2);		/* reply descriptor */	pascii(p, share);	pl16(p, 1);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */ 	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	conv = gl16(p);				/* rx buffer offset */	gl16(p);				/* number of entries returned */	gl16(p);				/* number of entries available */ 	if(err){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	memset(si2p, 0, sizeof(Shareinfo2)); 	gmem(p, tmp, 13);	tmp[13] = 0;	g8(p);					/* padding */	si2p->name = estrdup9p(tmp);	si2p->type = gl16(p);	gconv(p, conv, tmp, sizeof tmp);	si2p->comment = estrdup9p(tmp);	gl16(p);				/* comment offset high (unused) */	si2p->perms = gl16(p);	si2p->maxusrs = gl16(p);	si2p->activeusrs = gl16(p);	gconv(p, conv, tmp, sizeof tmp);	si2p->path = estrdup9p(tmp);	gl16(p);				/* path offset high (unused) */	gmem(p, tmp, 9);	tmp[9] = 0;	si2p->passwd = estrdup9p(tmp); 	free(p);	return 0;} /* * Tried to split sessionenum into two passes, one getting the names * of the connected workstations and the other collecting the detailed info, * however API_WSessionGetInfo doesn't seem to work agains win2k3 for infolevel * ten and infolevel one and two are priviledged calls.  This means this code * will work for small numbers of sessions agains win2k3 and fail for samba 3.0 * as it supports info levels zero and two only. */intRAPsessionenum(Session *s, Share *sp, Sessinfo **sip){	int ngot = 0, conv, err, navail, nret;	char tmp[1024];	Pkt *p;	Sessinfo *q; 	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WSessionEnum);	pascii(p, REMSmb_NetSessionEnum_P);	/* request descriptor */	pascii(p, REMSmb_session_info_10);	/* reply descriptor */	pl16(p, 10);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	conv = gl16(p);				/* rx buffer offset */	nret = gl16(p);				/* number of entries returned */	navail = gl16(p);			/* number of entries available */ 	if(err && err != RAP_ERR_MOREINFO){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	if(ngot == 0){		*sip = emalloc9p(sizeof(Sessinfo) * navail);		memset(*sip, 0, sizeof(Sessinfo) * navail);	} 	q = *sip + ngot;	while(nret-- != 0){		gconv(p, conv, tmp, sizeof tmp);		q->wrkstn = estrdup9p(tmp);		gconv(p, conv, tmp, sizeof tmp);		q->user = estrdup9p(tmp);		q->sesstime = gl32(p);		q->idletime = gl32(p);		ngot++;		q++;	}	if(ngot < navail)		fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);	free(p);	return ngot;}  intRAPgroupenum(Session *s, Share *sp, Namelist **nlp){	int ngot, err, navail, nret;	char tmp[1024];	Pkt *p;	Namelist *q; 	ngot = 0;	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WGroupEnum);	pascii(p, REMSmb_NetGroupEnum_P);	/* request descriptor */	pascii(p, REMSmb_group_info_0);		/* reply descriptor */	pl16(p, 0);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	gl16(p);				/* rx buffer offset */	nret = gl16(p);				/* number of entries returned */	navail = gl16(p);			/* number of entries available */ 	if(err && err != RAP_ERR_MOREINFO){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	*nlp = emalloc9p(sizeof(Namelist) * navail);	memset(*nlp, 0, sizeof(Namelist) * navail); 	q = *nlp + ngot;	while(ngot < navail && nret--){ 		gmem(p, tmp, 21);		tmp[21] = 0;		q->name = estrdup9p(tmp);		ngot++;		q++;		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */			break;	}	free(p);	return ngot;}  intRAPgroupusers(Session *s, Share *sp, char *group, Namelist **nlp){	int ngot, err, navail, nret;	char tmp[1024];	Pkt *p;	Namelist *q; 	ngot = 0;	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WGroupGetUsers);	pascii(p, REMSmb_NetGroupGetUsers_P);	/* request descriptor */	pascii(p, REMSmb_user_info_0);		/* reply descriptor */	pascii(p, group);			/* group name for list */	pl16(p, 0);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	gl16(p);				/* rx buffer offset */	nret = gl16(p);				/* number of entries returned */	navail = gl16(p);			/* number of entries available */ 	if(err && err != RAP_ERR_MOREINFO){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	*nlp = emalloc9p(sizeof(Namelist) * navail);	memset(*nlp, 0, sizeof(Namelist) * navail); 	q = *nlp + ngot;	while(ngot < navail && nret--){ 		gmem(p, tmp, 21);		tmp[21] = 0;		q->name = estrdup9p(tmp);		ngot++;		q++;		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */			break;	}	free(p);	return ngot;} intRAPuserenum(Session *s, Share *sp, Namelist **nlp){	int ngot, err, navail, nret;	char tmp[1024];	Pkt *p;	Namelist *q; 	ngot = 0;	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WUserEnum);	pascii(p, REMSmb_NetUserEnum_P);	/* request descriptor */	pascii(p, REMSmb_user_info_0);		/* reply descriptor */	pl16(p, 0);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */	gl16(p);				/* rx buffer offset */	nret = gl16(p);				/* number of entries returned */	navail = gl16(p);			/* number of entries available */ 	if(err && err != RAP_ERR_MOREINFO){		werrstr("%s", raperrstr(err));		free(p);		return -1;	} 	*nlp = emalloc9p(sizeof(Namelist) * navail);	memset(*nlp, 0, sizeof(Namelist) * navail); 	q = *nlp + ngot;	while(ngot < navail && nret--){ 		gmem(p, tmp, 21);		tmp[21] = 0;		q->name = estrdup9p(tmp);		ngot++;		q++;		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */			break;	}	free(p);	return ngot;} intRAPuserenum2(Session *s, Share *sp, Namelist **nlp){	int ngot, resume, err, navail, nret;	char tmp[1024];	Pkt *p;	Namelist *q; 	ngot = 0;	resume = 0;more:	p = thdr(s, sp);	pstr(p, "\\PIPE\\LANMAN");	ptparam(p); 	pl16(p, API_WUserEnum2);	pascii(p, REMSmb_NetUserEnum2_P);	/* request descriptor */	pascii(p, REMSmb_user_info_0);		/* reply descriptor */	pl16(p, 0);				/* detail level */	pl16(p, MTU - 200);			/* receive buffer length */	pl32(p, resume);			/* resume key to allow multiple fetches */	ptdata(p); 	if(trpc(p) == -1){		free(p);		return -1;	} 	gtparam(p);	err = gl16(p);				/* error code */

Lines 1–500 of 794.