Пример #1
0
Файл: app.c Проект: Juul/gnupg
/* Perform a GETATTR operation.  */
gpg_error_t
app_getattr (app_t app, ctrl_t ctrl, const char *name)
{
  gpg_error_t err;

  if (!app || !name || !*name)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);

  if (app->apptype && name && !strcmp (name, "APPTYPE"))
    {
      send_status_info (ctrl, "APPTYPE",
                        app->apptype, strlen (app->apptype), NULL, 0);
      return 0;
    }
  if (name && !strcmp (name, "SERIALNO"))
    {
      char *serial;
      time_t stamp;
      int rc;

      rc = app_get_serial_and_stamp (app, &serial, &stamp);
      if (rc)
        return rc;
      send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
      xfree (serial);
      return 0;
    }

  if (!app->fnc.getattr)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err =  app->fnc.getattr (app, ctrl, name);
  unlock_reader (app->slot);
  return err;
}
Пример #2
0
Файл: app.c Проект: Juul/gnupg
/* Write out the application specifig status lines for the LEARN
   command. */
gpg_error_t
app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
{
  gpg_error_t err;

  if (!app)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!app->ref_count)
    return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
  if (!app->fnc.learn_status)
    return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);

  /* We do not send APPTYPE if only keypairinfo is requested.  */
  if (app->apptype && !(flags & 1))
    send_status_info (ctrl, "APPTYPE",
                      app->apptype, strlen (app->apptype), NULL, 0);
  err = lock_reader (app->slot, ctrl);
  if (err)
    return err;
  err = app->fnc.learn_status (app, ctrl, flags);
  unlock_reader (app->slot);
  return err;
}
Пример #3
0
int loop_socket_handle(int socket, int tt_ms)
{
	unsigned char outhexbuf[ONE_TCP_MAX_LEN] = {0};
	PRO *pro = (PRO*)malloc(sizeof(PRO));
	memset(pro, 0, sizeof(PRO));
	pro->payload = (unsigned char*)malloc(ONLINE_MAX_LEN);
	memset(pro->payload, 0, (ONLINE_MAX_LEN));
	
	int ret = 0;
	int login_ok = 0;
	unsigned int sendseq = 0;
	int outinx = 0;
	int hexlen = 0;
	MACH_STAT stat = IDLE;
	
	while(1) {
		debug(LOG_NOTICE, "stat=%d,login_flag=%d,outinx=%d,last_cmd=%04x,last_recv_ret=%d,dev_work_status=%d\n",
							stat,login_ok,outinx,pro->hd.cmd,ret,dev_work_status);
		switch(stat) {
			case IDLE:
				//sleep_intp_s(5); //will block tcp recving
				break;
				
			case TO_LOGIN:
				memset(&pro->hd, 0, sizeof(PRO_HD));
				memset(pro->payload, 0, (ONLINE_MAX_LEN));
				send_login_info(socket, pro, sendseq++);
				break;
				
			case TO_DEVSTATUS:
				//recv_uart();
				//send_dev_data();
				if(glb_cfg.glb_sock != socket)
					glb_cfg.glb_sock = socket; // uart thread will write glb_sock directly.
				break;
				
			case TO_WORKSTATUS:
				memset(pro->payload, 0, (ONLINE_MAX_LEN));
				if(dev_work_status == E_DEV_TAKEUP) {
					send_busy_info(socket, pro, dev_work_status, sendseq++);
				} else {
					send_status_info(socket, pro, dev_work_status, sendseq++);
				}
				stat = IDLE;
				break;

			case TO_RESPSTATUS:
				memset(pro->payload, 0, (ONLINE_MAX_LEN));
				response_status_info(socket, pro, dev_work_status, sendseq++);
				stat = IDLE;
				break;
			
			case TO_HEART:
				memset(&pro->hd, 0, sizeof(PRO_HD));
				send_heart_info(socket, &pro->hd, sendseq++);
				if(outinx++ > HEART_EXIT_COUNT)
					goto EXIT_ERR;
				else
					stat = IDLE;
				break;
				
			case TO_RESP:
				//for testing;all back
				pro->hd.stat = PRO_RSP;
				memset(outhexbuf, 0, sizeof(outhexbuf));
				hexlen = 0;
				pro_pro2hexbuf(pro,outhexbuf,&hexlen);
				send(socket, outhexbuf, hexlen, sendseq++);
				debug(LOG_DEBUG, "Send Resp Len:%d\n",hexlen);
				stat = IDLE;
				break;
				
			case NET_DISCONN:
				goto EXIT_ERR;
				break;
			
			default:
				break;
		}
		
		//memset(pro, 0, sizeof(PRO)); //NOTE***: will init payload as NULL; this will cause crash!!!
		memset(&pro->hd, 0, sizeof(PRO_HD));
		memset(pro->payload, 0, (ONLINE_MAX_LEN));
		ret = socket_recv_tt(socket, pro, tt_ms);
		if(ret == 0) {
			// timeout
			if(!login_ok) {
				stat = TO_LOGIN;
			} else {
				stat = TO_HEART;
			}
		} else if(ret < 0) {
			// socket error
			goto EXIT_ERR;
			
		} else if( (ret != sizeof(PRO_HD)) && 
				   (ret != sizeof(PRO_HD)+pro->hd.len) ) {
			debug(LOG_NOTICE, "Recv Length %d Error!\n",ret);
			continue;
		} else {
			// handle data...
			switch(pro->hd.cmd) {
				case IDM_DEV_LOGIN:
					debug(LOG_NOTICE, "---< server back: login\n");
					login_ok = 1;
					if(dev_work_status != E_DEV_TAKEUP)
						dev_work_status = E_DEV_ONLINE;
					stat = TO_DEVSTATUS;
					break;
					
				case IDM_DEV_HEART:
					debug(LOG_NOTICE, "---< server back: heart\n");
					outinx = 0;
					break;
				
				case IDM_GETDEV:
					debug(LOG_NOTICE, "---< server cmd: get dev\n");
					stat = TO_RESPSTATUS;
					break;

				/* for response testing */
				case 0xfffe:
					debug(LOG_NOTICE, "---< server cmd: test response\n");
					stat = TO_RESP;
					break;
					
				case IDM_TAKEUPDEV:
				case IDM_RELEASEDEV:
				case IDM_RESET:
				case IDM_DOSTART:
				case IDM_DOSTOP:
				case IDM_SETPARS:
				case IDM_DELPARS:
					if(0 == memcmp(taskid, pro->payload+32, 32)) {
						break;
					} else {
						if(dev_work_status == E_DEV_TAKEUP) {
							debug(LOG_WARNING, "---< server taskid is not correct!\n");
							stat = TO_WORKSTATUS;
							continue;
						} else {
							/* Firstly takeup device */
							break;
						}
					}
				default:
					debug(LOG_ERR, "==== Handle: Unknow Server CMD 0x%02x\n", pro->hd.cmd);
					continue;
			}
			
			switch(pro->hd.cmd) {
				/* handle at local */
				case IDM_TAKEUPDEV:
					debug(LOG_NOTICE, "---< server cmd: takeup dev\n");
					dev_work_status = E_DEV_TAKEUP;
					stat = TO_WORKSTATUS;
					memcpy(taskid, pro->payload+32, sizeof(taskid)); /* skip devid 32*/
					break;

				case IDM_RELEASEDEV:
					debug(LOG_NOTICE, "---< server cmd: release dev\n");
					dev_work_status = E_DEV_ONLINE;
					stat = TO_WORKSTATUS;
					memset(taskid, 0, sizeof(taskid));
					break;
				
				/* send to uart */
				case IDM_RESET:
					debug(LOG_NOTICE, "---< server cmd: reset dev\n");
					dev_work_status = E_DEV_ONLINE;
					stat = TO_WORKSTATUS;
					/* stop and clear */
					dev_reset(pro->payload, pro->hd.len);
					break;

				case IDM_DOSTART:
					debug(LOG_NOTICE, "---< server cmd: start dev\n");
					glb_cfg.rsp_cmd_type = SVR_NEED_TASK_RET;
					glb_cfg.rsp_cmd_type |= SVR_NEED_TASK_PERCT;
					/* only send payload to uart */
					ret = dev_start(pro->payload, pro->hd.len);
					debug(LOG_DEBUG, "---Send To Com ret %d\n",ret);
					break;

				case IDM_DOSTOP:
					debug(LOG_NOTICE, "---< server cmd: stop dev\n");
					glb_cfg.rsp_cmd_type = SVR_NEED_TASK_RET;
					/* only send payload to uart */
					ret = dev_stop(pro->payload, pro->hd.len);
					debug(LOG_DEBUG, "---Send To Com ret %d\n",ret);
					break;

				case IDM_SETPARS:
					debug(LOG_NOTICE, "---< server cmd: set params dev\n");
					/* only send params to uart */
					ret = dev_setpar(pro->payload+64+2, (pro->hd.len-66)>0?(pro->hd.len-66):0);
					debug(LOG_DEBUG, "---Send To Com ret %d\n",ret);
					break;

				case IDM_DELPARS:
					debug(LOG_NOTICE, "---< server cmd: del params\n");
					/* only send payload to uart */
					ret = dev_clrpar(pro->payload, pro->hd.len);
					debug(LOG_DEBUG, "---Send To Com ret %d\n",ret);
					break;
			}
		}
		
		continue;
	} /* end while(1) */
	
EXIT_ERR:
	debug(LOG_NOTICE, "<--- Socket recv out!\n");
	glb_cfg.glb_sock = -1;
	glb_cfg.rsp_cmd_type = 0;
	if(socket > 0) close(socket);
	if(pro && pro->payload) {
		free(pro->payload);
		free(pro);
	}
	return -1;
}
Пример #4
0
gogoc_status tspStartLocal( int socket, tConf *c, tTunnel *t, net_tools_t *nt )
{
  TUNNEL_LOOP_CONFIG tun_loop_cfg;
  gogoc_status status = STATUS_SUCCESS_INIT;
  int ka_interval = 0;
  int tunfd = -1;
  //int pid;


  // Check if we got root privileges.
  if( geteuid() != 0 )
  {
    // Error: we don't have root privileges.
    Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_FATAL_NOT_ROOT_FOR_TUN );
    return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
  }

  // Check if we're already daemon. Calling multiple times the daemon() messes up pthreads.
  if( !c->nodaemon && getppid() != 1 )
  {
    // Detach from controlling terminal and run in the background.
    Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_GOING_DAEMON );
    if( daemon(1, 0) == -1 )
    {
      // Error: Failed to detach.
      Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_CANT_FORK );
      return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
    }
  }

  // Check tunnel mode.
  if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 )
  {
    // V4V6 encapsulation (DSTM) not supported on darwin.
    Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_NO_V4V6_ON_PLATFORM );
    return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
  }
  else if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 )
  {
    // When using V6UDPV4 encapsulation, open the TUN device.
    tunfd = TunInit(c->if_tunnel_v6udpv4);
    if( tunfd == -1 )
    {
      // Error: Failed to open TUN device.
      Display( LOG_LEVEL_1, ELError, "tspStartLocal", STR_MISC_FAIL_TUN_INIT );
      return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
    }

    // Get the real name of the opened tun device for the template script.
    free( c->if_tunnel_v6udpv4 );
    c->if_tunnel_v6udpv4 = (char*) malloc( IFNAMSIZ );
    TunName( tunfd, c->if_tunnel_v6udpv4, IFNAMSIZ );
  }

  t->originalgateway = routepr();
    
  while( 1 ) // Dummy loop. 'break' instruction at the end.
  {
    // Run the config script in another thread, without giving it our tunnel
    // descriptor. This is important because otherwise the tunnel will stay
    // open if we get killed.
    //
//    pid = fork();

//    if( pid < 0 )
//    {
      // fork() error
//      status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
//      break;
//    }
//    else if( pid == 0 )
//    {
      // Child processing: run template script.
//      if( tunfd != -1 )
//      {
//        close(tunfd);
//      }

      status = tspSetupInterface(c, t);
//      exit( status );
//    }
//    else
//    {
      // Parent processing
//      int s = 0;

      // Wait for child process to exit.
//      Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_WAITING_FOR_SETUP_SCRIPT );
//      if( wait(&s) != pid )
//      {
//        // Error occured: we have no other child
//        Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_ERR_WAITING_SCRIPT );
//        status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
//        break;
//      }

      // Check if process waited upon has exited.
//      if( !WIFEXITED(s) )
//      {
//        // Error: child has not exited properly. Maybe killed ?
//        Display( LOG_LEVEL_1, ELError, "tspStartLocal", STR_GEN_SCRIPT_EXEC_FAILED );
//        Display( LOG_LEVEL_1, ELError, "tspStartLocal", "status 0x%08X %s (%d).", s, strerror(s), errno);
//        status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED);
//        break;
//      }

      // Check child exit code.
//      status = WEXITSTATUS(s);
      if( status_number(status) != SUCCESS )
      {
        break;
      }
//    }
      
      gStatusInfo.eStatus = GOGOC_CLISTAT__CONNECTED;
      gStatusInfo.nStatus = GOGOCM_UIS__NOERROR;
      send_status_info();

    // Retrieve keepalive inteval, if found in tunnel parameters.
    if( t->keepalive_interval != NULL )
    {
      ka_interval = atoi(t->keepalive_interval);
    }

    // Start the tunnel loop, depending on tunnel mode
    //
    if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 )
    {
      status = TunMainLoop( tunfd, socket, c->keepalive,
                            ka_interval, t->client_address_ipv6,
                            t->keepalive_address );

      LOG( LOG_LEVEL_2, ELInfo, "end TunMainLoop. Starting tspClose.");
      // We got out of main V6UDPV4 loop.
      tspClose(socket, nt);
      LOG( LOG_LEVEL_2, ELInfo, "end tspClose.");
    }
    else if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6V4) == 0 )
    {
      memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) );
      tun_loop_cfg.ka_interval  = ka_interval;
      tun_loop_cfg.ka_src_addr  = t->client_address_ipv6;
      tun_loop_cfg.ka_dst_addr  = t->keepalive_address;
      tun_loop_cfg.sa_family    = AF_INET6;
      tun_loop_cfg.tun_lifetime = 0;

      status = tspPerformTunnelLoop( &tun_loop_cfg );
    }

    break; // END of DUMMY loop.
  }


  // Cleanup: Close tunnel descriptor, if it was opened.
  if( tunfd != -1 )
  {
    LOG( LOG_LEVEL_2, ELInfo, "Closing tunnel descriptor");
    // The tunnel file descriptor should be closed before attempting to tear
    // down the tunnel. Destruction of the tunnel interface may fail if
    // descriptor is not closed.
    close( tunfd );
  }

  // Cleanup: Handle tunnel teardown.
  LOG( LOG_LEVEL_2, ELInfo, "Handle tunnel teardown");
  tspTearDownTunnel( c, t );


  return status;
}