static inline int write_pad(struct arg_printf* fn, int len, int padwith) { int nr=0; for (;len>15;len-=16,nr+=16) { A_WRITE(fn,pad_line[(padwith=='0')?1:0],16); } if (len>0) { A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len; } return nr; }
static int write_pad(unsigned int* dlen,struct arg_printf* fn, unsigned int len, int padwith) { int nr=0; if ((int)len<0 || *dlen+len<len) return -1; for (;len>15;len-=16,nr+=16) { A_WRITE(fn,pad_line[(padwith=='0')?1:0],16); } if (len>0) { A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len; } *dlen += nr; return 0; }
static void do_channel_forward_receive(struct ssh_channel *c, int type, struct lsh_string *data) { CAST(channel_forward, closure, c); switch (type) { case CHANNEL_DATA: A_WRITE(&closure->socket->write_buffer->super, data); break; case CHANNEL_STDERR_DATA: werror("Ignoring unexpected stderr data.\n"); lsh_string_free(data); break; default: fatal("Internal error. do_channel_forward_receive"); } }
int __v_printf(struct arg_printf* fn, const unsigned char *format, va_list arg_ptr) { int len=0; #ifdef WANT_ERROR_PRINTF int _my_errno = errno; #endif while (*format) { unsigned int sz = skip_to(format); if (sz) { A_WRITE(fn,format,sz); len+=sz; format+=sz; } if (*format=='%') { char buf[2000]; union { char*s; } u_str; #define s u_str.s int retval; unsigned char ch, padwith=' '; char flag_in_sign=0; char flag_upcase=0; char flag_hash=0; char flag_left=0; char flag_space=0; char flag_sign=0; char flag_dot=0; signed char flag_long=0; unsigned int base; unsigned int width=0, preci=0; long number=0; #ifdef WANT_LONGLONG_PRINTF long long llnumber=0; #endif ++format; inn_printf: switch(ch=*format++) { case 0: return -1; break; /* FLAGS */ case '#': flag_hash=-1; case 'z': goto inn_printf; case 'h': --flag_long; goto inn_printf; case 'q': /* BSD ... */ case 'L': ++flag_long; /* fall through */ case 'l': ++flag_long; goto inn_printf; case '-': flag_left=1; goto inn_printf; case ' ': flag_space=1; goto inn_printf; case '+': flag_sign=1; goto inn_printf; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(flag_dot) return -1; width=strtoul(format-1,(char**)&s,10); if (ch=='0' && !flag_left) padwith='0'; format=s; goto inn_printf; case '*': width=va_arg(arg_ptr,int); goto inn_printf; case '.': flag_dot=1; if (*format=='*') { int tmp=va_arg(arg_ptr,int); preci=tmp<0?0:tmp; ++format; } else { long int tmp=strtol(format,(char**)&s,10); preci=tmp<0?0:tmp; format=s; } goto inn_printf; /* print a char or % */ case 'c': ch=(char)va_arg(arg_ptr,int); case '%': A_WRITE(fn,&ch,1); ++len; break; #ifdef WANT_ERROR_PRINTF /* print an error message */ case 'm': s=strerror(_my_errno); sz=strlen(s); A_WRITE(fn,s,sz); len+=sz; break; #endif /* print a string */ case 's': s=va_arg(arg_ptr,char *); #ifdef WANT_NULL_PRINTF if (!s) s="(null)"; #endif sz = strlen(s); if (flag_dot && sz>preci) sz=preci; preci=0; flag_dot^=flag_dot; padwith=' '; print_out: { char *sign=s; int todo=0; int vs; if (! (width||preci) ) { A_WRITE(fn,s,sz); len+=sz; break; } if (flag_in_sign) todo=1; if (flag_hash>0) todo=flag_hash; if (todo) { s+=todo; sz-=todo; width-=todo; } if (!flag_left) { if (flag_dot) { vs=preci>sz?preci:sz; len+=write_pad(fn,(signed int)width-(signed int)vs,' '); if (todo) { A_WRITE(fn,sign,todo); len+=todo; } len+=write_pad(fn,(signed int)preci-(signed int)sz,'0'); } else { if (todo && padwith=='0') { A_WRITE(fn,sign,todo); len+=todo; todo=0; } len+=write_pad(fn,(signed int)width-(signed int)sz, padwith); if (todo) { A_WRITE(fn,sign,todo); len+=todo; } } A_WRITE(fn,s,sz); len+=sz; } else if (flag_left) { if (todo) { A_WRITE(fn,sign,todo); len+=todo; } len+=write_pad(fn,(signed int)preci-(signed int)sz, '0'); A_WRITE(fn,s,sz); len+=sz; vs=preci>sz?preci:sz; len+=write_pad(fn,(signed int)width-(signed int)vs, ' '); } else { A_WRITE(fn,s,sz); len+=sz; } break; } /* print an integer value */ case 'b': base=2; sz=0; goto num_printf; case 'p': flag_hash=2; flag_long=1; ch='x'; case 'X': flag_upcase=(ch=='X'); case 'x': base=16; sz=0; if (flag_hash) { buf[1]='0'; buf[2]=ch; flag_hash=2; sz=2; } if (preci>width) width=preci; goto num_printf; case 'd': case 'i': flag_in_sign=1; case 'u': base=10; sz=0; goto num_printf; case 'o': base=8; sz=0; if (flag_hash) { buf[1]='0'; flag_hash=1; ++sz; } num_printf: s=buf+1; if (flag_long>0) { #ifdef WANT_LONGLONG_PRINTF if (flag_long>1) llnumber=va_arg(arg_ptr,long long); else #endif number=va_arg(arg_ptr,long); }
int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr) { int len=0; while (*format) { unsigned int sz = skip_to(format); if (sz) { A_WRITE(fn,format,sz); len+=sz; format+=sz; } if (*format=='%') { char buf[32]; char ch, padwith=' '; char *s; char flag_in_sign=0; char flag_upcase=0; char flag_hash=0; char flag_left=0; char flag_space=0; char flag_sign=0; char flag_dot=0; char flag_size_t = 0; signed char flag_long=0; unsigned int base; unsigned int width=0, preci=0; long int number=0; long long llnumber=0; unsigned int wh_sz; ++format; inn_printf: switch(ch=*format++) { case 0: return -1; break; /* FLAGS */ case '#': flag_hash=1; goto inn_printf; case 'h': --flag_long; goto inn_printf; case 'l': ++flag_long; goto inn_printf; case 'z': flag_size_t = 1; goto inn_printf; case '0': padwith='0'; goto inn_printf; case '-': flag_left=1; goto inn_printf; case ' ': flag_space=1; goto inn_printf; case '+': flag_sign=1; goto inn_printf; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(flag_dot) return -1; width=strtoul(format-1,&s,10); format=s; goto inn_printf; case '*': width=va_arg(arg_ptr,int); goto inn_printf; case '.': flag_dot=1; if (*format=='*') { preci=va_arg(arg_ptr,int); ++format; } else { long int tmp=strtol(format,&s,10); preci=tmp<0?0:tmp; format=s; } goto inn_printf; /* print a char or % */ case 'c': ch=(char)va_arg(arg_ptr,int); case '%': A_WRITE(fn,&ch,1); ++len; break; /* print a string */ case 's': s=va_arg(arg_ptr,char *); if (!s) s="(null)"; sz = visible_strlen(s, &wh_sz); // FIXME: could not limit output when invisibible charachters are // in the output if (sz == wh_sz && flag_dot && sz>preci) { sz = preci; wh_sz = sz; } print_out: if (width && (!flag_left)) { len+=write_pad(fn,(signed int)width-(signed int)sz,padwith); } A_WRITE(fn,s,wh_sz); len+=wh_sz; if (width && (flag_left)) { len+=write_pad(fn,(signed int)width-(signed int)sz,' '); } break; /* print an integer value */ case 'b': base=2; sz=0; goto num_printf; case 'p': flag_hash=1; if(sizeof(void*)>sizeof(unsigned)) ++flag_long; if(sizeof(void*)>sizeof(long)) ++flag_long; ch='x'; case 'X': flag_upcase=(ch=='X'); case 'x': base=16; sz=0; if (flag_hash) { buf[1]='0'; buf[2]=ch; sz=2; } goto num_printf; case 'd': case 'i': flag_in_sign=1; case 'u': base=10; sz=0; goto num_printf; case 'o': base=8; sz=0; if (flag_hash) { buf[1]='0'; ++sz; } num_printf: if (flag_long>0) { if (flag_long>1) llnumber=va_arg(arg_ptr,long long); else number=va_arg(arg_ptr,long); }
/* FIXME: This function is a little ugly. It would get cleaner if we * just replaced the channel's receive function pointer with NULL on * failure and do_channel_forward_receive on success. */ static void do_client_channel_x11_receive(struct ssh_channel *s, int type, struct lsh_string *data) { CAST(client_x11_channel, self, s); if (type != CHANNEL_DATA) { werror("Ignoring unexpected stderr data.\n"); lsh_string_free(data); } else switch (self->state) { case CLIENT_X11_OK: A_WRITE(&self->super.socket->write_buffer->super, data); break; fail: channel_close(&self->super.super); self->state = CLIENT_X11_DENIED; break; case CLIENT_X11_DENIED: /* Any data on the channel should be stopped before we get * here; the CHANNEL_SENT_CLOSE should be set. */ fatal("Internal error!\n"); default: { /* Copy data to buffer */ UINT32 left = self->buffer->length - self->i; /* The small initial window size should ensure that we don't get * more data. */ assert(data->length <= left); memcpy(self->buffer->data + self->i, data->data, data->length); self->i += data->length; lsh_string_free(data); switch (self->state) { case CLIENT_X11_START: /* We need byte-order, major, minor and name_length, * which is 6 octets */ if (self->i < X11_SETUP_HEADER_LENGTH) break; self->state = CLIENT_X11_GOT_LENGTHS; switch (self->buffer->data[0]) { case 'B': /* Big endian */ case 'b': /* Big endian */ self->little_endian = 0; self->name_length = READ_UINT16(self->buffer->data + 6); self->auth_length = READ_UINT16(self->buffer->data + 8); break; case 'L': /* Little endian */ case 'l': /* Little endian */ self->little_endian = 1; self->name_length = LE_READ_UINT16(self->buffer->data + 6); self->auth_length = LE_READ_UINT16(self->buffer->data + 8); break; default: werror("client_x11.c: Bad endian indicator.\n"); goto fail; } if ( (self->name_length > 20) || (self->auth_length > 16) ) { werror("client_x11.c: Too long auth name or cookie\n"); goto fail; } /* Fall through */ case CLIENT_X11_GOT_LENGTHS: { const unsigned pad_length[4] = { 0, 3, 2, 1 }; #define PAD(l) (pad_length[ (l) % 4]) UINT32 auth_offset = X11_SETUP_HEADER_LENGTH + self->name_length + PAD(self->name_length); UINT32 length = auth_offset + self->auth_length + pad_length[self->auth_length % 4]; if (self->i < length) break; debug("Received cookie of type `%ps': %xs\n", self->name_length, self->buffer->data + X11_SETUP_HEADER_LENGTH, self->auth_length, self->buffer->data + auth_offset); /* Ok, now we have the connection setup message. Check if it's ok. */ if ( (self->name_length == MIT_COOKIE_NAME_LENGTH) && !memcmp(self->buffer->data + X11_SETUP_HEADER_LENGTH, MIT_COOKIE_NAME, MIT_COOKIE_NAME_LENGTH) && lsh_string_eq_l(self->display->fake, self->auth_length, self->buffer->data + auth_offset)) { struct lsh_string *msg; UINT8 lengths[4]; static const UINT8 pad[3] = { 0, 0, 0 }; /* Cookies match! */ verbose("client_x11: Allowing X11 connection; cookies match.\n"); if (self->little_endian) { LE_WRITE_UINT16(lengths, self->display->auth_name->length); LE_WRITE_UINT16(lengths + 2, self->display->auth_data->length); } else { WRITE_UINT16(lengths, self->display->auth_name->length); WRITE_UINT16(lengths + 2, self->display->auth_data->length); } /* FIXME: Perhaps it would be easier to build the message by hand than * using ssh_format? */ /* Construct the real setup message. */ msg = ssh_format("%ls%ls%c%c%ls%ls%ls%ls", X11_SETUP_VERSION_LENGTH, self->buffer->data, 4, lengths, 0, 0, self->display->auth_name->length, self->display->auth_name->data, PAD(self->display->auth_name->length), pad, self->display->auth_data->length, self->display->auth_data->data, self->i - length, self->buffer + self->i); lsh_string_free(self->buffer); self->buffer = NULL; /* Bump window size */ channel_start_receive(&self->super.super, X11_WINDOW_SIZE - msg->length); debug("client_x11.c: Sending real X11 setup message: %xS\n", msg); /* Send real x11 connection setup message. */ A_WRITE(&self->super.socket->write_buffer->super, msg); self->state = CLIENT_X11_OK; } else { werror("client_x11: X11 connection denied; bad cookie.\n"); goto fail; } break; #undef PAD } default: fatal("Internal error. do_client_channel_x11_receive"); break; } } break; } }