Yaroslav Kolomiietsfew renames52ec96d7 years agoHistory
526 lines · 10.1 KB · C
RawDownload
/* Based on: T.128 Multipoint application sharing */#include <u.h>#include <libc.h>#include "dat.h"#include "fns.h" static const char	srcDesc[] = "Plan 9";	/* sourceDescriptor (T.128 section 8.4.1) */ enum{	Bits4=		0x0F, 	/* 2.2.9.1.1.3.1.2.2 Bitmap Data */	Bcompress=	1,	Pcompress=	0x20, 	/* 2.2.8.1.1.1.1 Share Control Header */	PDUactivate	= 1,	/* Demand Active PDU (section 2.2.1.13.1) */	PDUactivated	= 3,	/* Confirm Active PDU (section 2.2.1.13.2) */	PDUdeactivate	= 6,	/* Deactivate All PDU (section 2.2.3.1) */	PDUdata		= 7,	/* Data PDU */ 	/* 2.2.9.1.1.4 Server Pointer Update PDU (TS_POINTER_PDU) */	PDUcursorwarp=	3, 	/* 2.2.1.11.1.1 Info Packet (TS_INFO_PACKET) */	InfMouse=	1<<0,	InfNoctlaltdel=	1<<1,	InfAutologon=	1<<3,	InfUnicode=	1<<4,	InfMaxshell=	1<<5,	InfCompress=	1<<7,	InfWinkey=	1<<8,	Compress64k=	1<<9,	// RDP 5.0 bulk compression (3.1.8.4.2) 	PerfNoDrag=	1<<1,	PerfNoAnim=	1<<2,	PerfNoTheming=	1<<3,	PerfNoCursorset=	1<<6,	PerfFontAA=	1<<7,		/* 2.2.9.1.1.3.1 Slow-Path Graphics Update (TS_GRAPHICS_UPDATE) */	UpdOrders=	0, 		 	UpdBitmap=	1,	/* section 2.2.9.1.1.3.1.2 */	UpdCmap=	2,	/* section 2.2.9.1.1.3.1.1 */ 	/* 2.2.9.1.2.1 Fast-Path Update (TS_FP_UPDATE) */	FUpdOrders=	0,	FUpdBitmap=	1,	FUpdCmap=	2,	FUpdWarp=	8, 	/* 2.2.7.1.1 General Capability Set (TS_GENERAL_CAPABILITYSET) */	NoBitcomphdr	= 0x0400,};  /* 2.2.9.1.2.1 Fast-Path Update (TS_FP_UPDATE) * * updateHeader[1] compressionFlags[1]? size[2] updateData[*] */intgetshareF(Share* as, uchar* a, uint nbytes){	int hd, nb, cflags, ulen;	uchar *p,  *ep, *q; 	as->type = 0;	if(nbytes < 3){		werrstr(Eshort);		return -1;	} 	p = a;	ep = a+nbytes; 	hd = *p++;	if(hd&(1<<7))		cflags = *p++;	else		cflags = 0;	if(p+2 > ep){		werrstr(Eshort);		return -1;	}	nb = igets(p);	p += 2;	q = p+nb;	if(cflags&Pcompress){		if(p+nb > ep){			werrstr("bad length %d in Fast-Path PDU header", nb);			return -1;		}		if((p = uncomp(p, nb, cflags, &ulen)) == nil){			werrstr("fast-path packet de-compression failed: %r cflags=%#x", cflags);			return -1;		}		ep = p+ulen;	} 	switch(hd&Bits4){	case FUpdOrders:		if(p+2>ep){			werrstr(Eshort);			return -1;		}		as->type = ShUorders;		as->nr = igets(p);		as->data = p+2;		as->ndata = ep-(p+2);		break;	case FUpdBitmap:		if(p+4>ep){			werrstr(Eshort);			return -1;		}		as->type = ShUimg;		as->nr = igets(p+2);		as->data = p+4;		as->ndata = ep-(p+4);		break;	case FUpdCmap:		as->type = ShUcmap;		as->data = p;		as->ndata = ep-p;		break;	case FUpdWarp:		if(p+4>ep){			werrstr(Eshort);			return -1;		}		as->type = ShUwarp;		as->x = igets(p+0);		as->y = igets(p+2);		break;	}	return q-a;} /*  * T.128 ASPDU * * 2.2.8.1.1.1.1 Share Control Header * https://msdn.microsoft.com/en-us/library/cc240576.aspx *  * totalLength[2] pduType[2] pduSource[2] */intgetshareT(Share* as, uchar* p, uint nb){	int len, nsrc, type;	int pduType2, ctype, mtype, uptype, clen, ulen, ulenr;	uchar *ep; 	as->type = 0;	if(nb < 6){		werrstr(Eshort);		return -1;	}	len = igets(p);	if(len < SCHSIZE || len > nb){		werrstr("bad length in Share Control PDU header");		return -1;	}	type = igets(p+2)&Bits4;	as->source = igets(p+4); 	switch(type){	case PDUactivate:		/*		 * 2.2.1.13.1 Server Demand Active PDU		 * http://msdn.microsoft.com/en-us/library/cc240484.aspx		 */		as->type = ShActivate;		if(len<14){			werrstr(Eshort);			return -1;		}		as->shareid = igetl(p+6);		nsrc = igets(p+10);		as->ndata = igets(p+12);		if(len<14+nsrc+as->ndata){			werrstr(Eshort);			return -1;		}		as->data = p+14+nsrc;		as->ncap = igets(p+14+nsrc);		break;	case PDUdeactivate:		as->type = ShDeactivate;		break;	case PDUdata:		/*		 * 2.2.8.1.1.1.2 Share Data Header (TS_SHAREDATAHEADER)		 * http://msdn.microsoft.com/en-us/library/cc240577.aspx		 *		 * shareId[4] pad1[1] streamId[1] uncomprLen[2]		 * pduType2[1] comprType[1] comprLen[2]		 */		ep = p+nb;			if(nb < 18){			werrstr("%s (%ud<18)", Eshort, nb);			return -1;		}			ulen = igets(p+12);		pduType2 = p[14];		ctype = p[15];		clen = igets(p+16) - SCDSIZE;		p += 18;			if(ctype&(1<<5)){			if(p+clen > ep){				werrstr(Eshort);				return -1;			}			if((p = uncomp(p, clen, ctype, &ulenr)) == nil){				werrstr("decompression failed: %r");				return -1;			}			if(ulen != ulenr+SCDSIZE){				werrstr("bad length after decompression");				return -1;			}			ep = p+ulenr;		}			switch (pduType2){		case ADsync:			as->type = ShSync;			break;		case ADctl:			as->type = ShCtl;			break;		case ADfontmap:	/* denotes completion of the connection sequence */			as->type = ShFmap;			break;		case ADerrx:			/* 2.2.5.1.1 Set Error Info PDU Data (TS_SET_ERROR_INFO_PDU) */			if(p+4 > ep){				werrstr("ADdraw: %s", Eshort);				return -1;			}			as->type = ShEinfo;			as->err = igetl(p);			break;		case ADdraw:			/* 2.2.9.1.1.3.1 Slow-Path Graphics Update (TS_GRAPHICS_UPDATE) */			/* not when Fast-Path is in use */			if(p+2 > ep){				werrstr("ADdraw: %s", Eshort);				return -1;			}			uptype = igets(p);			switch(uptype){			case UpdOrders:				if(p+8 > ep){					werrstr("ShUorders: %s", Eshort);					return -1;				}				as->type = ShUorders;				as->nr = igets(p+4);				as->data = p+8;				as->ndata = ep-(p+8);				break;			case UpdBitmap:				if(p+4 > ep){					werrstr("ShUimg: %s", Eshort);					return -1;				}				as->type = ShUimg;				as->nr = igets(p+2);				as->data = p+4;				as->ndata = ep-(p+4);				break;			case UpdCmap:				as->type = ShUcmap;				as->data = p;				as->ndata = ep-p;				break;			}			break;		case ADcursor:			/* 2.2.9.1.1.4 Server Pointer Update PDU (TS_POINTER_PDU) */			if(p+2 > ep){				werrstr(Eshort);				return -1;			}			mtype = igets(p);			if(mtype == PDUcursorwarp){				if(p+8 > ep){					werrstr(Eshort);					return -1;				}				as->type = ShUwarp;				as->x = igets(p+4);				as->y = igets(p+6);				break;			}		}		break;	}	return len;} /* 2.2.9.1.1.3.1.2.2 Bitmap Data (TS_BITMAP_DATA) */intgetimgupd(Imgupd* u, uchar* a, uint nb){	uchar *p, *ep, *s;	int opt, len; 	p = a;	ep = a+nb;	if(nb < 18){		werrstr(Eshort);		return -1;	}	u->type = Ubitmap;	u->x = igets(p+0);	u->y = igets(p+2);	u->xm = igets(p+4);	u->ym = igets(p+6);	u->xsz = igets(p+8);	u->ysz = igets(p+10);	u->depth = igets(p+12);	opt = igets(p+14);	len = igets(p+16);	p += 18;	s = p+len;	if(s > ep){		werrstr(Eshort);		return -1;	}	u->compressed = (opt&Bcompress);	if(opt&Bcompress && !(opt&NoBitcomphdr))		p += 8;	u->bytes = p;	u->nbytes = s-p;	return s-a;} /* T.128 FlowPDU */intisflowpdu(uchar* p, uchar* ep){	int marker; 	if(p+2 > ep){		werrstr(Eshort);		return -1;	}	marker = igets(p);	return marker == 0x8000;} /* 2.2.1.13.2 Client Confirm Active PDU */intputconfirmactive(uchar* b, uint nb, Msg* m){	uchar *p, *q, *ep;	int n, nsrc, capsize, ndata, pdusize;	int userchan, shareid, originid;	Caps caps; 	assert(m->type == Mactivated);	userchan = m->mcsuid;	shareid = m->shareid;	originid = m->originid; 	caps.depth = m->depth;	caps.xsz = m->xsz;	caps.ysz = m->ysz;		nsrc = sizeof(srcDesc);	capsize = sizecaps(&caps);	ndata = 16+nsrc+capsize; 	p = txprep(b, nb, ndata, 0, userchan, 0);	if(p == nil)		sysfatal("buffer not prepared: %r");	ep = p+ndata;	pdusize = ep-b;	q = p; 	/* 2.2.8.1.1.1.1 Share Control Header */	/* totalLength[2] pduType[2] PDUSource[2] */	iputs(p+0, ndata);	iputs(p+2, PDUactivated | (1<<4));	iputs(p+4, userchan); 	/* shareId[4] originatorId[2] sdlen[2] caplen[2] srcdesc[sdlen] ncap[2] pad[2] */	iputl(p+6, shareid);	iputs(p+10, originid);	iputs(p+12, nsrc);	iputs(p+14, capsize);	memcpy(p+16, srcDesc, nsrc);	p += nsrc+16;	if((n = putcaps(p, ep-p, &caps)) < 0)		sysfatal("putcaps: %r");	p += n;	assert(p-ndata == q);	return pdusize;} /* 2.2.1.11 Client Info PDU */intputclientinfo(uchar* b, uint nb, Msg* m){	uchar *p, *q;	int ndata, usize;	int opt, perfopt;	int ndom, nusr, npw, nsh, nwd;	uchar *wdom, *wusr, *wpw, *wsh, *wwd;		char *dom, *usr, *pw, *sh, *wd;		int dologin; 	assert(m->type == Dclientinfo);	dom = m->dom;	usr = m->user;	pw = m->pass;	sh = m->rshell;	wd = m->rwd;	dologin = m->dologin; 	ndom = strlen(dom)+1;	nusr = strlen(usr)+1;	npw = strlen(pw)+1;	nsh = strlen(sh)+1;	nwd = strlen(wd)+1;	wdom = emalloc(4*ndom);	wusr = emalloc(4*nusr);	wpw = emalloc(4*npw);	wsh = emalloc(4*nsh);	wwd = emalloc(4*nwd);	ndom = toutf16(wdom, 4*ndom, dom, ndom);	nusr = toutf16(wusr, 4*nusr, usr, nusr);	npw = toutf16(wpw, 4*npw, pw, npw);	nsh = toutf16(wsh, 4*nsh, sh, nsh);	nwd = toutf16(wwd, 4*nwd, wd, nwd); 	ndata = 18+ndom+nusr+npw+nsh+nwd+188;		opt = 0		| InfMouse		| InfUnicode		| InfNoctlaltdel		| InfMaxshell		| InfWinkey		| InfCompress		| Compress64k		;	if(dologin)		opt |= InfAutologon;	perfopt = 0		| PerfNoDrag		| PerfNoAnim		| PerfNoCursorset		| PerfNoTheming		| PerfFontAA		; 	p = txprep(b, nb, ndata, 0, m->mcsuid, Sinfopk);	if(p == nil)		return -1;	usize = p+ndata-b;	q = p; 	iputl(q+0, 0);	// codePage; langId when opt&InfUnicode	iputl(q+4, opt);	iputs(q+8, ndom-2);	iputs(q+10, nusr-2);	iputs(q+12, npw-2);	iputs(q+14, nsh-2);	iputs(q+16, nwd-2);	q += 18;	memcpy(q, wdom, ndom);	q += ndom;	memcpy(q, wusr, nusr);	q += nusr;	memcpy(q, wpw, npw);	q += npw;	memcpy(q, wsh, nsh);	q += nsh;	memcpy(q, wwd, nwd);	q += nwd; 	iputs(q+0, 2);	// cbClientAddress 	iputs(q+2, 0);	// clientAddress	iputs(q+4, 2);	// cbClientDir	iputs(q+6, 0);	// clientDir	memset(q+8, 172, 0);	// clientTimeZone	iputl(q+180, 0);	// clientSessionId	iputl(q+184, perfopt);	// performanceFlags 	q += 188; 	assert(q == p+ndata); 	free(wdom);

Lines 1–500 of 526.