Пример #1
0
static void
rwrite(Fcall *f)
{
    Fid *fidp;
    int n;
    char *err, *argv[10];

    fidp = newfid(f->fid);
    if(fidp->node->d.mode & DMDIR) {
        reply(f, "directories are not writable");
        return;
    }
    if(fidp->open == 0) {
        reply(f, "file not open");
        return;
    }

    if (!permitted(fidp, fidp->node, AWRITE)) {
        reply(f, "permission denied");
        return;
    }

    f->data[f->count] = 0;			/* the extra byte in rbuf leaves room */
    n = tokenize(f->data, argv, 10);
    err = 0;
    switch(findkey(argv[0], cmds)) {
    case RELOAD:
        getconf();
        reload();
        break;
    case RDEBUG:
        if(n > 1) {
            debugfd = create(argv[1], OWRITE, 0666);
            if(debugfd < 0)
                err = "create failed";
        } else
            debugfd = 2;
        break;
    case RNODEBUG:
        if(debugfd >= 0)
            close(debugfd);
        debugfd = -1;
        break;
    default:
        err = "unknown command";
        break;
    }
    reply(f, err);
}
Пример #2
0
/*
  add_host -- add the given host to the list of permitted hosts, provided it isn't
              already there.
*/
static void
add_host (unsigned long host_addr)
{
  int key;
  struct entry *new_entry;

  if (!permitted(host_addr, -1))
    {
      if ((new_entry = (struct entry *) malloc(sizeof(struct entry))) == NULL) {
	fprintf(stderr,"%s: unable to malloc space for permitted host entry\n",
		progname);
	exit(1);
      } /* if */

      new_entry->host_addr = host_addr;
      key = HASH(host_addr) % TABLE_SIZE;
      new_entry->next = permitted_hosts[key];
      permitted_hosts[key] = new_entry;
    } /* if */

} /* add_host */
Пример #3
0
Файл: delete.cpp Проект: aox/aox
void Delete::execute()
{
    if ( state() != Executing || !ok() )
        return;

    if ( d->first ) {
        d->first = false;

        // We should really require DeleteMessages and Expunge only if
        // we know the mailbox isn't empty; but we'll know that inside
        // the transaction, and permitted() won't let us clean that up
        // if we don't have permission. So it'll have to wait until we
        // query permissions ourselves.

        requireRight( d->m, Permissions::DeleteMailbox );
        requireRight( d->m, Permissions::DeleteMessages );
        requireRight( d->m, Permissions::Expunge );
    }

    if ( !permitted() )
        return;

    if ( !transaction() ) {
        setTransaction( new Transaction( this ) );
        Query * lock = new Query( "select * from mailboxes "
                                  "where id=$1 for update", 0 );
        lock->bind( 1, d->m->id() );
        transaction()->enqueue( lock );

        d->messages = new Query( "select count(mm.uid)::bigint as messages "
                                 "from mailbox_messages mm "
                                 "join messages m on (mm.message=m.id) "
                                 "join mailboxes mb on (mm.mailbox=mb.id) "
                                 "where mm.mailbox=$1 and not mm.seen and "
                                 "(mm.uid>=mb.first_recent or m.idate>$2)",
                                 this );
        d->messages->bind( 1, d->m->id() );
        Date now;
        now.setCurrentTime();
        d->messages->bind( 2, now.unixTime() - 20 );
        transaction()->enqueue( d->messages );
        transaction()->execute();
    }

    if ( d->messages ) {
        if ( !d->messages->done() )
            return;

        int64 messages = 0;

        Row * r = d->messages->nextRow();
        if ( d->messages->failed() || !r )
            error( No, "Could not determine if any messages exist" );
        else
            messages = r->getBigint( "messages" );

        if ( messages )
            error( No, "Cannot delete mailbox: " + fn( messages ) +
                   " messages exist" );
        d->messages = 0;

        if ( ok() && d->m->remove( transaction() ) == 0 )
            error( No, "Cannot delete mailbox " + d->m->name().ascii() );

        Mailbox::refreshMailboxes( transaction() );
        transaction()->commit();
    }

    if ( !transaction()->done() )
        return;

    if ( transaction()->failed() ) {
        error( No, "Database error: " + transaction()->error() );
        return;
    }

    finish();
}
Пример #4
0
Файл: status.cpp Проект: aox/aox
void Status::execute()
{
    if ( state() != Executing )
        return;

    // first part. set up.
    if ( !permitted() )
        return;

    Session * session = imap()->session();
    Mailbox * current = 0;
    if ( session )
        current = session->mailbox();

    // second part. see if anything has happened, and feed the cache if
    // so. make sure we feed the cache at once.
    if ( d->unseenCount || d->recentCount || d->messageCount ) {
        if ( d->unseenCount && !d->unseenCount->done() )
            return;
        if ( d->messageCount && !d->messageCount->done() )
            return;
        if ( d->recentCount && !d->recentCount->done() )
            return;
    }
    if ( !::cache )
        ::cache = new StatusData::StatusCache;

    if ( d->unseenCount ) {
        while ( d->unseenCount->hasResults() ) {
            Row * r = d->unseenCount->nextRow();
            StatusData::CacheItem * ci =
                ::cache->find( r->getInt( "mailbox" ) );
            if ( ci ) {
                ci->hasUnseen = true;
                ci->unseen = r->getInt( "unseen" );
            }
        }
    }
    if ( d->recentCount ) {
        while ( d->recentCount->hasResults() ) {
            Row * r = d->recentCount->nextRow();
            StatusData::CacheItem * ci =
                ::cache->find( r->getInt( "mailbox" ) );
            if ( ci ) {
                ci->hasRecent = true;
                ci->recent = r->getInt( "recent" );
            }
        }
    }
    if ( d->messageCount ) {
        while ( d->messageCount->hasResults() ) {
            Row * r = d->messageCount->nextRow();
            StatusData::CacheItem * ci =
                ::cache->find( r->getInt( "mailbox" ) );
            if ( ci ) {
                ci->hasMessages = true;
                ci->messages = r->getInt( "messages" );
            }
        }
    }

    // third part. are we processing the first command in a STATUS
    // loop? if so, see if we ought to preload the cache.
    if ( mailboxGroup() && d->cacheState < 3 ) {
        IntegerSet mailboxes;
        if ( d->cacheState < 1 ) {
            // cache state 0: decide which messages
            List<Mailbox>::Iterator i( mailboxGroup()->contents() );
            while ( i ) {
                StatusData::CacheItem * ci = ::cache->provide( i );
                bool need = false;
                if ( d->unseen || d->recent || d->messages )
                    need = true;
                if ( ci->hasUnseen || ci->hasRecent || ci->hasMessages )
                    need = false;
                if ( need )
                    mailboxes.add( i->id() );
                ++i;
            }
            if ( mailboxes.count() < 3 )
                d->cacheState = 3;
        }
        if ( d->cacheState == 1 ) {
            // state 1: send queries
            if ( d->unseen ) {
                d->unseenCount
                    = new Query( "select mailbox, count(uid)::int as unseen "
                                 "from mailbox_messages "
                                 "where mailbox=any($1) and not seen "
                                 "group by mailbox", this );
                d->unseenCount->bind( 1, mailboxes );
                d->unseenCount->execute();
            }
            if ( d->recent ) {
                d->recentCount
                    = new Query( "select id as mailbox, "
                                 "uidnext-first_recent as recent "
                                 "from mailboxes where id=any($1)", this );
                d->recentCount->bind( 1, mailboxes );
                d->recentCount->execute();
            }
            if ( d->messages ) {
                d->messageCount
                    = new Query( "select count(*)::int as messages, mailbox "
                                 "from mailbox_messages where mailbox=any($1) "
                                 "group by mailbox", this );
                d->messageCount->bind( 1, mailboxes );
                d->messageCount->execute();
            }
            d->cacheState = 2;
        }
        if ( d->cacheState == 2 ) {
            // state 2: mark the cache as complete.
            IntegerSet mailboxes;
            List<Mailbox>::Iterator i( mailboxGroup()->contents() );
            while ( i ) {
                StatusData::CacheItem * ci = ::cache->find( i->id() );
                if ( ci && d->unseenCount )
                    ci->hasUnseen = true;
                if ( ci && d->recentCount )
                    ci->hasRecent = true;
                if ( ci && d->messageCount )
                    ci->hasMessages = true;
                ++i;
            }
            // and drop the queries
            d->cacheState = 3;
            d->unseenCount = 0;
            d->recentCount = 0;
            d->messageCount = 0;
        }
    }

    // the cache item we'll actually read from
    StatusData::CacheItem * i = ::cache->provide( d->mailbox );

    // fourth part: send individual queries if there's anything we need
    if ( d->unseen && !d->unseenCount && !i->hasUnseen ) {
        d->unseenCount
            = new Query( "select $1::int as mailbox, "
                         "count(uid)::int as unseen "
                         "from mailbox_messages "
                         "where mailbox=$1 and not seen", this );
        d->unseenCount->bind( 1, d->mailbox->id() );
        d->unseenCount->execute();
    }

    if ( !d->recent ) {
        // nothing doing
    }
    else if ( d->mailbox == current ) {
        // we'll pick it up from the session
    }
    else if ( i->hasRecent ) {
        // the cache has it
    }
    else if ( !d->recentCount ) {
        d->recentCount
            = new Query( "select id as mailbox, "
                         "uidnext-first_recent as recent "
                         "from mailboxes where id=$1", this );
        d->recentCount->bind( 1, d->mailbox->id() );
        d->recentCount->execute();
    }

    if ( !d->messages ) {
        // we don't need to collect
    }
    else if ( d->mailbox == current ) {
        // we'll pick it up
    }
    else if ( i->hasMessages ) {
        // the cache has it
    }
    else if ( d->messages && !d->messageCount ) {
        d->messageCount
            = new Query( "select count(*)::int as messages, "
                         "$1::int as mailbox "
                         "from mailbox_messages where mailbox=$1", this );
        d->messageCount->bind( 1, d->mailbox->id() );
        d->messageCount->execute();
    }

    if ( d->unseenCount || d->recentCount || d->messageCount ) {
        if ( d->unseenCount && !d->unseenCount->done() )
            return;
        if ( d->messageCount && !d->messageCount->done() )
            return;
        if ( d->recentCount && !d->recentCount->done() )
            return;
    }

    // fifth part: return the payload.
    EStringList status;

    if ( d->messages && i->hasMessages )
        status.append( "MESSAGES " + fn( i->messages ) );
    else if ( d->messages && d->mailbox == current )
        status.append( "MESSAGES " + fn( session->messages().count() ) );

    if ( d->recent && i->hasRecent )
        status.append( "RECENT " + fn( i->recent ) );
    else if ( d->recent && d->mailbox == current )
        status.append( "RECENT " + fn( session->recent().count() ) );

    if ( d->uidnext )
        status.append( "UIDNEXT " + fn( d->mailbox->uidnext() ) );

    if ( d->uidvalidity )
        status.append( "UIDVALIDITY " + fn( d->mailbox->uidvalidity() ) );

    if ( d->unseen && i->hasUnseen )
        status.append( "UNSEEN " + fn( i->unseen ) );

    if ( d->modseq ) {
        int64 hms = d->mailbox->nextModSeq();
        // don't like this. an empty mailbox will have a STATUS HMS of
        // 1 before it receives its first message, and also 1 after.
        if ( hms > 1 )
            hms--;
        status.append( "HIGHESTMODSEQ " + fn( hms ) );
    }

    respond( "STATUS " + imapQuoted( d->mailbox ) +
             " (" + status.join( " " ) + ")" );
    finish();
}
Пример #5
0
static UDP_Assoc *newUA(Connection *Conn,UDP_Assoc *uav[],PCStr(clhost),int clport,PCStr(svhost),int svport)
{	int ux;
	UDP_Assoc *ua;
	int svsock;
	int rcode;
	CStr(msg,128);
	CStr(lhost,256);
	int lport;
	CStr(local,256);
	CStr(remote,256);
	int SOCKSctl = -1;
	CStr(rh,256);
	int rp;

	rcode = -1;
	if( !permitted(clhost,clport,svhost,svport) )
		return NULL;

	sprintf(local,"*:*");
	sprintf(remote,"%s:%d",svhost,svport);
	Conn->from_cached = 1;
	VA_setClientAddr(Conn,clhost,clport,0);
	Conn->no_dstcheck_proto = serviceport("tcprelay");
	initConnect(Conn);
	setupConnect(Conn);

	ServerFlags |= PF_UDP;
	Conn->sv.p_SOCKSCTL = -1;
	svsock = connectViaSocks(Conn,svhost,svport,AVStr(rh),&rp);
	if( 0 <= svsock ){
		sv1log("via SOCKS UDP:%d@%s CTL:%d\n",svsock,
			Conn->sv.p_SOCKSADDR,Conn->sv.p_SOCKSCTL);
		SOCKSctl = Conn->sv.p_SOCKSCTL;
		goto ADDUA;
	}

	svsock = VSocket(Conn,"CNCT/UDPRELAY",-1,AVStr(local),AVStr(remote),"");
	if( 0 <= svsock ){
/*
		setNonblockingIO("UDPRELAY-SV",svsock,1);
*/
		SetNonblockingIO("UDPRELAY-SV",svsock,1);
		goto ADDUA;
	}

	strcpy(lhost,"*");
	lport = 0;
	SRCIFfor(Conn,"udprelay",svhost,svport,AVStr(lhost),&lport);
	if( strcmp(lhost,"*") == 0 )
		lhost[0] = 0;

	svsock = server_open("UDPRELAY",AVStr(lhost),lport,-1);
	if( svsock < 0 ){
		if( uav[0] == 0 ){
			return NULL;
		}
		ux = longestIdle(uav);
		sv1log("push out longest idle 1 [%d]\n",ux);
		delUA(uav,ux,"NoMoreSocket",1);
		svsock = server_open("UDPRELAY",AVStr(lhost),lport,-1);
		if( svsock < 0 )
			return NULL;
	}

	if( UDPRELAY_RPORT_FIX ){
	rcode = __connectServer(svsock,"UDPRELAY","udprelay",svhost,svport /*,1*/);
	if( rcode < 0 ){
		sv1log("UDPRELAY: connect(%d) error %d\n",svsock,rcode);
		close(svsock);
		return NULL;
	}
	}

ADDUA:
	for( ux = 0; uav[ux]; ux++ )
		;
	if( UDPRELAY_MAXASSOC <= ux ){
		ux = longestIdle(uav);
		sv1log("push out longest idle 2 [%d]\n",ux);
		delUA(uav,ux,"NoMoreClient",0);
	}

	ua = (UDP_Assoc*)calloc(1,sizeof(UDP_Assoc));
	ua->ua_id = ++uaid;
	ua->ua_ctime = time(0);
	ua->ua_clhost = stralloc(clhost);
	ua->ua_clport = clport;
	ua->ua_svsock = svsock;
	ua->ua_svbound = (0 < peerPort(svsock));
	ua->ua_svtcp = !isUDPsock(svsock);
	ua->ua_svhost = stralloc(svhost);
	ua->ua_svport = svport;
	ua->ua_svSOCKS = SOCKSctl;
	VSA_aptosa(&ua->ua_SOCKSADDR,Conn->sv.p_SOCKSADDR);
	uav[ux] = ua;

	msghead(AVStr(msg),"start",ua,ux);
	sv1log("%s > %s:%d\n",msg,svhost,svport);
	return ua;
}